Made progress on my game and now I need to make the second boss bounce up and down. I figured out how to make the boss go down, but once it touches the lower wall, it stops and won't bounce (move up).
void BossMove()
{
if((BOSS.Top + 10) <(this.Height - BOSS.Height))
{
BOSS.Top += 10;
}
if((BOSS.Height) > 0)
{
BOSS.Top -= 10;
}
}
Here's a simple example using a state variable to represent the direction:
private Boolean goingUp = true;
void BossMove()
{
if (goingUp)
{
if ((BOSS.Top + 10) < (this.Height - BOSS.Height))
{
BOSS.Top += 10;
}
else
{
// possibly force it to snap to specific position
// before going back down?
goingUp = false;
}
}
else
{
if (BOSS.Top > 450)
{
BOSS.Top -= 10;
}
else
{
// possibly force it to snap to specific position
// before going back up?
goingUp = true;
}
}
}
Related
Good day everyone, currently I am developing a simple 2D game using SWINGAME. I have set a collision between 2 objects. So when they collide, I want to temporarily make one of them invisible for a certain time. I am stuck about the time component, let's say I want the object to be invisible for 3 seconds after that it will change back to the default object. Below are the two images, if the collision is true then it will display image2, or else display image1. BTW I use a different image to indicate the invisibility. Here's my code.
Player class:
public void Draw ()
{
if (invisible == true) {
if(elapsedTime <= 3.0){
elapsedTime += elapsedTime;
SwinGame.DrawBitmap ("image2.png", (float)X, (float)Y);
}
}else {
elapsedTime = 0;
SwinGame.DrawBitmap ("image1.png", (float)X, (float)Y);
}
}
public bool Invisible {
get { return invisible; }
set { invisible = value; }
}
Object Collision class :
{... //Some codes
for(int i = 0; i < _obstacles.Count; i++)
{
if (_obstacles [i] is Invisible) {
p.Invisible = true;
p.Draw ();
}
}
//Some codes ...}
This should help you to calculate the time accurately by using the StopWatch class:
//somewhere in your code
Stopwatch sw = new Stopwatch();
sw.Start();
public void Draw ()
{
if (invisible == true) {
if(sw.ElapsedMilliseconds <= 3000){
SwinGame.DrawBitmap ("image2.png", (float)X, (float)Y);
}
}else {
sw.Restart();
SwinGame.DrawBitmap ("image1.png", (float)X, (float)Y);
}
}
Background: first of all I know some of my code is messy, please don't hate me. Basically I want to animate the movement of a TextBox object on a Windows Forms window. I have managed to do this by using a Timer. However, the rest of my code executes whilst the timer is running (and so the TextBox is still moving). How do I stop this from happening.
Here is some of my code:
move method:
private void move(int x, int y)
{
xValue = x;
yValue = y;
// Check to see if x co-ord needs moving up or down
if (xValue > txtData.Location.X) // UP
{
xDir = 1;
}
else if (xValue < box.Location.X) // DOWN
{
xDir = -1;
}
else // No change
{
.xDir = 0;
}
if (yValue > box.Location.Y) // RIGHT
{
yDir = 1;
}
else if (yValue < Location.Y) // LEFT
{
yDir = -1;
}
else // No change
{
yDir = 0;
}
timer.Start();
}
Timer Tick method:
private void timer_Tick(object sender, EventArgs e)
{
while (xValue != box.Location.X && yValue != box.Location.Y)
{
if (yDir == 0)
{
box.SetBounds(box.Location.X + xDir, box.Location.Y, box.Width, box.Height);
}
else
{
box.SetBounds(box.Location.X, box.Location.Y + yDir, box.Width, box.Height);
}
}
}
move calls:
move(478, 267);
move(647, 267);
move(647, 257);
I'm not sure exactly what you're asking, but if you're trying to force the program to stop running code until the animation is done, you could try using async await. You'll need at least .Net 4.5 to use async await, however.
private async void moveData(int x, int y)
{
Variables.xValue = x;
Variables.yValue = y;
// Check to see if x co-ord needs moving up or down
if (Variables.xValue > txtData.Location.X) // UP
{
Variables.xDir = 1;
}
else if (Variables.xValue < txtData.Location.X) // DOWN
{
Variables.xDir = -1;
}
else // No change
{
Variables.xDir = 0;
}
// Check to see if y co-ord needs moving left or right
if (Variables.yValue > txtData.Location.Y) // RIGHT
{
Variables.yDir = 1;
}
else if (Variables.yValue < txtData.Location.Y) // LEFT
{
Variables.yDir = -1;
}
else // No change
{
Variables.yDir = 0;
}
await Animate();
}
private async Task Animate()
{
while (Variables.xValue != txtData.Location.X && Variables.yValue != txtData.Location.Y)
{
if (Variables.yDir == 0) // If we are moving in the x direction
{
txtData.SetBounds(txtData.Location.X + Variables.xDir, txtData.Location.Y, txtData.Width, txtData.Height);
}
else // We are moving in the y direction
{
txtData.SetBounds(txtData.Location.X, txtData.Location.Y + Variables.yDir, txtData.Width, txtData.Height);
}
await Task.Delay(intervalBetweenMovements);
}
}
This way it will wait for move(x, y) to complete before moving to the next line.
First of all, im totally new to C# and I have to work on an Windows Store App for a study project.
I decided to develop an App, where you have to keep a ball in the air (with a paddle at the bottom of the field, nearly the same as in the classic pong game), which was really stupid cause I literally have no idea how to do this.
My code looks like this at the moment:
void Timer_Tick(object sender, object e)
{
Rect rectBall = new Rect(BallTransform.TranslateX, BallTransform.TranslateY, RectBall.ActualWidth, RectBall.ActualHeight);
Rect rectPaddle = new Rect(PaddleTransform.TranslateX, PaddleTransform.TranslateY, RectPaddle.ActualWidth, RectPaddle.ActualHeight);
rectPaddle.Intersect(rectBall);
int counter = 0;
Score.Text = ("Score: " + counter);
if (rectPaddle.IsEmpty == true)
{
BallTransform.TranslateY += 20;
}
if (BallTransform.TranslateY - 50 > PaddleTransform.TranslateY)
{
BallTransform.TranslateY -= 20;
Result.Text = ("Game Over!");
}
//if (rectPaddle.IsEmpty == false)
//{
// counter += 1;
// BallTransform.TranslateY -= 20;
// Score.Text = ("Score: " + counter);
//}
}
void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
switch (args.VirtualKey)
{
case Windows.System.VirtualKey.A:
PaddleTransform.TranslateX -= 40;
break;
case Windows.System.VirtualKey.D:
PaddleTransform.TranslateX += 40;
break;
case Windows.System.VirtualKey.Left:
PaddleTransform.TranslateX -= 40;
break;
case Windows.System.VirtualKey.Right:
PaddleTransform.TranslateX += 40;
break;
default:
break;
}
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
PaddleTransform.TranslateY = Grid.ActualHeight - RectPaddle.ActualHeight - 20;
PaddleTransform.TranslateX = (Grid.ActualWidth / 2) - RectPaddle.ActualWidth;
BallTransform.TranslateX = (Grid.ActualWidth / 2) - RectBall.ActualWidth;
DispatcherTimer Timer = new DispatcherTimer();
Timer.Interval = new TimeSpan(100);
Timer.Tick += Timer_Tick;
Timer.Start();
}
}
}
I know that this is not really much, and it doesn´t really do anything than letting the ball fall down, if it touches the paddle, it just stays where it is and if it misses the paddle, it´s "game over".
My biggest problem is, to find out how to let the ball jump up again after falling on the paddle, and give it different bouncing directions after doing this. Also I don´t know how I should handle the speed of the ball.
I´d be really happy if someone could explain me what i should do.
Thanks in advance!
PS: I read a lot of "Pong" and "Ball physic" tutorials, but they didn´t really help me.
A simple way of doing this is to keep track of the velocity of the ball in a separate variable, and using that to update its translation.
ie something along the lines of this: (example is not complete, but i hope you get the gist of it)
float BallXVel = 10;
float BallYVel = 20;
void Timer_Tick(object sender, object e)
{
//always move the ball.
BallTransform.TranslateX += BallXVel;
BallTransform.TranslateY += BallYVel;
//bounce the ball up if it hits the paddle and is not already moving up
if (!rectPaddle.IsEmpty && BallYVel > 0)
{
BallYVel = 0-BallYVel;
}
if (BallTransform.TranslateY - 50 > PaddleTransform.TranslateY)
{
BallTransform.TranslateY -= 20;
Result.Text = ("Game Over!");
}
}
My friends I made some parts of this game but I have two problems in this game.
1)Problem about distinguishing ball collision with obstacles
1-1)A first problem is related to complex guidelines that I used them for simulation of ball collision with board or ball collision with blocks. These guidelines are not accurate especially when the ball meets with block corner or bottom.
If it is not better for collision distinguish I use a better code. I wrote this code. Are you think that are there better way?
2)How I can do a work that if the ball collision with any obstacle, the obstacle report the collision.
My aim is about using of events.
Are you thinking that I make obstacles as runtime?
If I make as a runtime, how I can make collision event for them?
With best regards
private Point MouseDownLocation;
int step = 2;
int stepleft = 2;
bool flagBottom;
bool flagTop;
private void Form1_Load(object sender, EventArgs e)
{
timer1.Interval = 10;
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
ball.Top += step;
ball.Left += stepleft;
//board simulate collision
bool collisonX = ball.Location.X + ball.Width > board.Location.X && ball.Location.X < board.Location.X + board.Width;
bool collisonY = ball.Top + ball.Height == board.Location.Y || ball.Top + ball.Height - 1 == board.Location.Y;
//board2(button1) simulate collision
bool collisonX2 = ball.Location.X + ball.Width > board2.Location.X && ball.Location.X < board2.Location.X + board2.Width;
bool collisonY2 = ball.Top + ball.Height == board2.Location.Y || ball.Top + ball.Height - 1 == board2.Location.Y;
//Collision the ball with under buttons
bool collsionButtonY = ball.Top - ball.Height == board2.Location.Y || ball.Top - ball.Height == board2.Location.Y - 1;
//collision leftwall
bool leftWall = ball.Left == 0 || ball.Left == -1 || ball.Left == 1;
//collision rightwall
bool topWall = ball.Top == 0 || ball.Top == -1 || ball.Top == 1;
bool bottomWall = collisonX && collisonY;
bool toppWall = collisonX2 && collisonY2;
//collision
bool barrier = collisonX2 && collsionButtonY;
//rightwall
bool rightWall = ball.Left + ball.Width == this.ClientSize.Width || ball.Left + ball.Width == this.ClientSize.Width - 1;
// sidewall = collision rightwall or leftwall
bool sideWall = leftWall || rightWall;
//Check the ball hit the ground
bool check = ball.Top + ball.Height < this.ClientSize.Height;
//if topWall true,This means that the ball is hit to the topwall
if (topWall)
{
flagBottom = false;
flagTop = true;
if (stepleft > 0)
{
step = 2;
}
else if (stepleft < 0)
{
step = 2;
}
}
//if bottomWall true,This means that the ball is hit to the board
else if (bottomWall)
{
flagBottom = true;
flagTop = false;
if (stepleft > 0)
{
step = step * -1;
}
else if (stepleft < 0)
{
step = step * -1;
}
}
//if barrier true and flagbottom true,This means that the ball is hit to the board2(button1)
else if (barrier && flagBottom)
{
if (stepleft > 0)
{
step = step * -1;
}
else if (stepleft < 0)
{
step = step * -1;
}
}
//if toppWall true and flagTop true,This means that the ball is hit to The top button is hit
else if (toppWall && flagTop)
{
if (stepleft > 0)
{
step = step * -1;
}
else if (stepleft < 0)
{
step = step * -1;
}
}
else if (sideWall)
{
//if leftwall true,This means that the ball is hit to the left side wall
if (leftWall)
{
if (flagTop)
{
stepleft = 2;
}
else if (flagBottom)
{
stepleft = 2;
}
}
//if rightWall true,This means that the ball is hit to the left side wall
else if (rightWall)
{
if (flagTop)
{
stepleft = -2;
}
else if (flagBottom)
{
stepleft = -2;
}
}
}
//check if ckeck==ture,this mean the ball is hit the ground
else if (!check)
{
timer1.Enabled = false;
}
}
private void board_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
private void board_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
board.Left = e.X + board.Left - MouseDownLocation.X;
}
}
Define each "Wall" as an Object, this will increase your codes readablility. it will also allow you to define an Event for each wall, Listen to t. that way you know which wall has been hit
N.b. this is pseudo code. It wont compile :P
public class Wall
{
int X,Y,W,H;
//Define an event, add a listener to this, becuase we will fire this when there is a collision
public event EventHandler OnCollision;
public void CollisionCheck(Ball playerBall)
{
//1 Check for a collision with the "Ball" object
if(Ball.Rectangle().Intersects(this.Rectangle))
this.OnCollision(this, EventArgs.Empty); //Fire the event, null check might be requried
}
}
I do not know your game but (suspect 2D brick-like game)
Objects/Obstacles
all objects/obstacles can be simplified to rectangular objects
so make list of them with defined parameters like size and position
if they are movable/dropable then also speed and state...
type of object (affects color,scoring,capabilities...)
create member function like update(dt),draw()
create events you like OnHIt,OnCollision,...
for example (C++ pseudo code):
// game object types ...
enum _game_object_type_enum
{
_game_object_type_none=0,
_game_object_type_wall,
_game_object_type_brick1,
_game_object_type_brick2,
_game_object_type_brick3,
_game_object_type_bomb,
_game_object_type_joker1,
_game_object_type_joker2,
...
};
// game object class
class game_object
{
public;
int type; // type of object
float x,y,vx,vy,hx,hy; // position,speed,half size of rectangle
void update(float dt); // this call periodicaly in some timer updates positions,... and call events, dt is time passed
void draw(); // can add some rendering device context ...
};
// whole game class holds the game world/board/map and player(s) ...
class game_board
{
public;
game_object *go; int gos; // list of all objects in game
void update(float dt) { for (int i=0;i<gos;i++) go[i].update(dt); }
void draw() { for (int i=0;i<gos;i++) go[i].draw(); }
}
events and flow control
first define some events you need
either you use global function/pointers for that or as members
depends on your platform and to what you are used to
for example like this:
void OnCollisionFX(game_object o1,game_object o2)
{
// do something ...
}
void (*OnCollision)(game_object o1,game_object o2)=OnCollisionFX;
for player interactions only (like player controlled object collisions test only)
is better to handle this in game_object::update(dt) but you need to add player context
something like game_object::update(dt,plr)
where plr is pointer to player controlled object or player class
if you have massive interactivity between game objects (like brick/brick collisions)
then is better to handle this in game_board::update(dt)
because otherwise you will need to provide references for everything into update call
and that will quickly lead to heap/stack trashing and very slow performance
also more advanced multiple object collision/interaction approaches are better in main game class
here is an example for first case:
void game_object::update(float dt,game_object &plr)
{
// update position
x+=vx*dt;
y+=vy*dt;
// here you should make your own collision test of coarse
if (fabs(x-plr.x)<=hx+plr.hx)
if (fabs(y-plr.y)<=hy+plr.hy)
{
... do what you need like mirror or stop speed or clamp position ...
if (OnCollision) OnCollision(this,plr);
}
}
in second case you should check each object against each other
void game_board::update(float dt)
{
int i,j;
// update position
for (i=0;i<gos;i++)
{
go[i].x+=go[i].vx*dt;
go[i].y+=go[i].vy*dt;
}
// here you should make your own collision test of coarse
for (i=0;i<gos;i++)
for (j=i+1;j<gos;j++) // the lower indexes are already tested
if (fabs(go[i].x-go[j].x)<=go[i].hx+go[j].hx)
if (fabs(go[i].y-go[j].y)<=go[i].hy+go[j].hy)
{
... do what you need like mirror or stop speed or clamp position ...
if (OnCollision) OnCollision(go[i],go[j]);
}
}
performance
you can improve performance by use of type property
for example if some game objets are static then the do not need to update position
if some are indestructible then there can be also some processing avoided and so on ...
[notes]
dt/fps/speed should be combined
so in each frame your player controlled object or any moving object does not move further
then the half size of smallest object
if this is not true then you need better collision test
use line intersection algorithm
last position and actual position gives you one line
and object edge gives you the other one
if booth objects are moving then that is even more complicated :)
I am back with another question. I am still new to SFML so this one seemed a bit tough. I have tried using while loops and such but to no avail.
The game I am doing at the moment is a car going back and forth on the X axis and then I guess will be able to pick up points and stuff or simply just avoid objects coming towards the car until it eventually dies.
How do I make the movement smoother? Currently the car will move 8 units first, before moving 8 units in the desired direction until I let go of the button. It's the same when I do it the other way. I would like it to just instantly move and keep moving when I press either key.
static void OnKeyPressed(object sender, EventArgs e)
{
Vector2f newPos = new Vector2f(0, car.Position.Y);
KeyEventArgs ke = (KeyEventArgs)e;
if (ke.Code.Equals(Keyboard.Key.A))
{
if (car.Position.X != 0)
{
newPos.X = car.Position.X - 8;
car.Position = newPos;
}
else if (car.Position.X < 0)
{
newPos.X = 0;
car.Position = newPos;
}
else if(car.Position.X == 0)
{
// Do nothing
}
}
else if (ke.Code.Equals(Keyboard.Key.D))
{
if (car.Position.X != window.Size.X - 32)
{
newPos.X = car.Position.X + 8;
car.Position = newPos;
}
else if (car.Position.X > window.Size.X)
{
newPos.X = window.Size.X;
car.Position = newPos;
}
else if (car.Position.X == window.Size.X)
{
// Do nothing
}
}
}
And the entire thing for reference:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SFML.Audio;
using SFML.Graphics;
using SFML.Window;
namespace SFMLCarGame
{
class Program
{
private static RenderWindow window;
private static Sprite car;
static void Main(string[] args)
{
window = new RenderWindow(new VideoMode(256,512), "Car Game");
window.Closed += new EventHandler(OnClose);
window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
Sprite bg = new Sprite(new Texture("road.png"));
car = new Sprite(new Texture("car.png"));
car.Position = new Vector2f(window.Size.X / 2, window.Size.Y - 96);
while (window.IsOpen())
{
window.DispatchEvents();
window.Clear();
window.Draw(bg);
window.Draw(car);
window.Display();
}
}
static void OnClose(object sender, EventArgs e)
{
RenderWindow window = (RenderWindow)sender;
window.Close();
}
static void OnKeyPressed(object sender, EventArgs e)
{
Vector2f newPos = new Vector2f(0, car.Position.Y);
KeyEventArgs ke = (KeyEventArgs)e;
if (ke.Code.Equals(Keyboard.Key.A))
{
if (car.Position.X != 0)
{
newPos.X = car.Position.X - 8;
car.Position = newPos;
}
else if (car.Position.X < 0)
{
newPos.X = 0;
car.Position = newPos;
}
else if(car.Position.X == 0)
{
// Do nothing
}
}
else if (ke.Code.Equals(Keyboard.Key.D))
{
if (car.Position.X != window.Size.X - 32)
{
newPos.X = car.Position.X + 8;
car.Position = newPos;
}
else if (car.Position.X > window.Size.X)
{
newPos.X = window.Size.X;
car.Position = newPos;
}
else if (car.Position.X == window.Size.X)
{
// Do nothing
}
}
}
}
}
You may want to read this short tutorial from the SFML's website.
The events are fired by the operating system, and are good for certain purposes (quit event, a key is pressed, the left mouse button is clicked) but aren't for things that need to be updated really often. Imagine that you are writing some text, and keep the 'A' key pressed. Your text will progressively grow like aaaaaaaaaaa but there is a little delay between the a spawns, imposed by the OS. You would get, say, 6 letters by second. This is the same with events. With a game running and displaying at 60 fps it is clear that your movement will not be smooth and barely manageable.
Hopefully SFML provides a way to check the instant state of the keyboard (and mouse and joystick). With the C# binding (I am assuming you are using the binding for 2.0 version, and if you don't then you should) you only have to check Keyboard.isKeyPressed(yourKey).
Doing this in the main loop will check at each frame that the key is pressed, and not wait for an OS event that is way slower.
On a side note, if your previous questions were answered correctly please mark them so by accepting an answer.
Edit : I haven't SFML for .NET installed on my computer but here is what it could look like
static void Main(string[] args)
{
window = new RenderWindow(new VideoMode(256,512), "Car Game");
window.Closed += new EventHandler(OnClose);
// Note this
// window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
Sprite bg = new Sprite(new Texture("road.png"));
car = new Sprite(new Texture("car.png"));
car.Position = new Vector2f(window.Size.X / 2, window.Size.Y - 96);
while (window.IsOpen())
{
window.DispatchEvents();
CheckInputs(); // and this !
window.Clear();
window.Draw(bg);
window.Draw(car);
window.Display();
}
}
void CheckInputs()
{
if(Keyboard.isKeyPressed(Keyboard.key.A))
{
if(car.Position.X < 0)
car.Position.X = 0
else if(car.Position.X > 0)
car.Position.X -= 8; // shortcut for 'car.Position.X = car.Position.X - 8'
}
else if(Keyboard.isKeyPressed(Keyboard.key.D))
{
// etc
}
}
This way your transition should be much smoother, but beware, 8 pixels might be very fast !
I really recommend you to read the tutorial I have linked, because it explains the functionning of inputs in an language-agnostic way (even if the examples are in C++).
Also, you don't need your event handler anymore so I commented it. But if you are checking for other keys (like escape for pause or whatever) don't delete it, just remove the part you wrote about moving the car.