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!");
}
}
Related
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;
}
}
}
Now I am reading a book C # Programming for the Absolute Beginner
In Chapter 7, Section workouts, which put it.My question is that
The Interval property of a timer is specified in milliseconds, not ticks.
Now, how can I change the value of a variable(dy) based on each tick
Modify the difficulty level of the Lunar Lander game. There are several ways you could
tweak the code. Perhaps you could change gravity by modifying the change in dy during
each tick of the timer. You could also adjust how much dx and dy change during each key
press or how fast time progresses by modifying the timer’s interval. Another easy change
would be to modify the size of the landing pad or the lander.
public partial class theForm : Form
{
private double x, y; //will show new position of lander
private double dx, dy; //diffrence in x and y
private int fuel = 100; //how much fuel is left
private int ships = 3; // number of ships player has
private int score = 0; //the player's current score
private int level = 1;
public theForm()
{
InitializeComponent();
initGame();
}
private void timer1_Tick(object sender, EventArgs e)
{
//account for gravity
dy += 0.5;
//increment score for being alive
score += 100;
//show ordinary (no flames) lander
picLander.Image = myPics.Images[0];
//call helper methods to handle details
moveShip();
checkLanding();
showStats();
}//end timer tick
private void showStats()
{
//display the statistics
lblDx.Text = "dx: " + dx;
lblDy.Text = "dy: " + dy;
lblFuel.Text = "fuel: " + fuel;
lblShips.Text = "ships: " + ships;
lblScore.Text = "score: " + score;
}//end showStats
private void checkLanding()
{
//get rectangle from the objects
Rectangle rLander = picLander.Bounds;
Rectangle rPlatform = picPlatform.Bounds;
//look for an interesection
if (rLander.IntersectsWith(rPlatform))
{
//it's either a crash or a landing
//turn off the timer for a moment
timer1.Enabled = false;
if (Math.Abs(dx) < 3)
{
//horizontal speed ok
if (Math.Abs(dy) < 5)
{
//vertical speed ok
if (Math.Abs(rLander.Bottom - rPlatform.Top) < 3)
{
//landing on top of platform
MessageBox.Show("Good Landing!");
lblLevel.Text=Convert.ToString(level++);
fuel += 30;
score += 1000;
}
else
{
//not on top of platform
MessageBox.Show("You have to land on top.");
killShip();
}//end vertical if
}
else
{
//dy too large
MessageBox.Show("Too much vertical velocity!");
killShip();
} // end vertical if
}
else
{
//dx too large
MessageBox.Show("too much horizontal velocity");
killShip();
}//end horiz if
//reset the lander
initGame();
}//end if
}//end checkLanding
private void initGame()
{
//re-initializes the game
Random roller = new Random();
int platX, platY;
//find random dx,dy values for lander
dx = Convert.ToDouble(roller.Next(5) - 2);
dy = Convert.ToDouble(roller.Next(5) - 2);
//place lander randomly on form
x = Convert.ToDouble(roller.Next(this.ClientSize.Width));
y = Convert.ToDouble(roller.Next(this.ClientSize.Height));
//place platform randomly on form (but make sure it appears)
platX = roller.Next(this.ClientSize.Width - picPlatform.Width);
platY = roller.Next(this.ClientSize.Height - picPlatform.Height);
picPlatform.Location = new Point(platX, platY);
//turn on timer
timer1.Enabled = true;
}//end initGame
private void killShip()
{
//kill off a ship,check for end of game
DialogResult answer;
ships--;
if (ships <= 0)
{
//game is over
answer = MessageBox.Show("Play Again?", "Game Over", MessageBoxButtons.YesNo);
if (answer == DialogResult.Yes)
{
ships = 3;
fuel = 100;
initGame();
}
else
{
Application.Exit();
}//end if
}//end 'no ships' if
}//end killShip
private void theForm_KeyDown(object sender, KeyEventArgs e)
{
fuel--;
//check to see if user is out of gas
if (fuel < 0)
{
timer1.Enabled = false;
MessageBox.Show("Out of Fuel!!!");
fuel += 20;
killShip();
initGame();
}//end if
//look for arrow keys
switch (e.KeyData)
{
case Keys.Up:
picLander.Image = myPics.Images[1];
dy -= 2;
break;
case Keys.Left:
picLander.Image = myPics.Images[2];
dx++;
break;
case Keys.Right:
picLander.Image = myPics.Images[3];
dx--;
break;
default:
//do nothing
break;
}//end switch
if(e.KeyCode==Keys.Up && level==2)
{
dy -= 3;
}else if(e.KeyCode == Keys.Left && level== 2)
{
dx += 2;
}else if(e.KeyCode == Keys.Right && level == 2)
{
dx -= 2;
}
}//end keydown
private void moveShip()
{
//change x and check for boundaries
x += dx;
if (x > this.Width - picLander.Width)
{
x = 0;
}
if (x < 0)
{
x = Convert.ToDouble(this.Width - picLander.Width);
}//end if
//change y and check for boundaries
y += dy;
if (y < 0)
{
y = Convert.ToDouble(this.Height - picLander.Height);
}//end if
if (y > this.Height - picLander.Height)
{
y = 0;
}//end if
//move picLander to new location
picLander.Location = new Point(Convert.ToInt32(x), Convert.ToInt32(y));
}//end MoveShip
private void theForm_Load(object sender, EventArgs e)
{
}
}
You can use the 'Tick' event of the timer.
public Form1()
{
InitializeComponent();
Timer timer = new Timer();
timer.Tick += Timer_Tick;
}
private void Timer_Tick(object sender, EventArgs e)
{
//Your code goes here
}
Hi guys I have searched for an answer but I have not found a particular answer that would help me. So I am asking this question.
My question is how do you detect if your picturebox moves outside the window or form.
Each tick of my timer does:
picturebox.Left += 10;
if (picturebox.Left > this.Width)
{
picturebox.Left = 0;
}
But this code only goes to the right side and only detects if the picturebox went out on the right side of the form.
I have tried doing something like lets say I'm moving the picturebox to the left and it went out of the screen, this is the code I have got and this doesnt give any error but it will move my image so fast then.
picturebox.Left -= 10;
if (picturebox.Left > this.width || picturebox.Left < this.Width)
{
picturebox.Left = 0;
}
This piece of code doesnt work for me either:
picturebox.Right < this.Width
Please help,
Thanks
Here's one way...
private int direction = -1;
private void button1_Click(object sender, EventArgs e)
{
direction = direction * -1;
}
private void timer1_Tick(object sender, EventArgs e)
{
picturebox.Left += direction * 10;
if (!this.ClientRectangle.IntersectsWith(picturebox.Bounds))
{
if (direction == -1)
picturebox.Left = this.ClientRectangle.Width;
else
picturebox.Left = -picturebox.Width;
}
}
Try this.
private bool IsControlInsideClientArea(Control c)
{
return this.ClientRectangle.Contains(this.RectangleToClient(c.RectangleToScreen(c.ClientRectangle)));
}
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.
I have a delightful rectangle named ship, which I control with the right and left arrow keys. When I initially press a key ship moves in the opposite direction it should for the first movement, then goes back the right way. What would be an elegant solution to this particular conundrum?
public double p = 0;
private void Window_KeyDown_1(object sender, KeyEventArgs e)
{
if (e.Key == Key.Right)
{
ship.Margin = new Thickness(p, 259, 0, 12);
p = p + 10;
}
if (e.Key == Key.Left)
{
ship.Margin = new Thickness(p, 259, 0, 12);
p = p - 10;
}
You're changing the value of p after you set the margin. That means you're effectively always one key-press behind. I would expect you to want to set it before you make the change. (I'm not sure that setting the margin is really the ideal way of moving something around, mind you...)
Consier removing field for current left margin. You can get current ship margin before you change it. Also split handling user input and ship movement operations:
// Handle user input
private void Window_KeyDown_1(object sender, KeyEventArgs e)
{
switch(e.Key)
{
case (Key.Right):
MoveShip(Direction.Right); return;
case (Key.Left):
MoveShip(Direction.Left); return;
default:
return;
}
}
// Here you implement ship movement (Margin, Canvas.SetLeft, etc)
private void MoveShip(Direction direction)
{
var margin = ship.Margin; // or create copy here
const int distance = 10;
switch(direction)
{
case(Direction.Left):
margin.Left -= distance;
break;
case(Direction.Right):
margin.Left += distance;
break;
default:
return;
}
ship.Margin = margin;
}
private enum Direction
{
Left,
Right
}