I am developing a game where I have a speed variable and a player x and player y.
Here is the up directional movement for my player:
I use an if statement in my up method in order to check if the player is breaking the boundaries of my frame.
public void createCharacter(Player player) {
Character.player = player;
speed = 1;
character.setIcon(CharacterSheet.downRightLeg);
Game.game.add(character);
px = 200;
py = 200;
character.setBounds(px, py, 56, 63);
}
public static void up() {
if (py - 2 > 0) {
player.setPlayerDirection(1);
py -= speed;
renderUpwardWalking();
character.setLocation(px, py);
Game.user.setLocation(px, py - 50);
} else if (py - 2 < 0) {
}
}
I call createCharacter at the beginning of the game when a player logs in.
Can I set int speed to a double and give it a value like .5? I tried it and it didn't work. My character moves too fast for the game I'm making and I don't know how to slow him down.
Related
It's basically a simple game, in that, when the mouse pointer is within the circle, it adds one to the score. I'm new to processing and tried to create this simple game.
Here's the code:
float dist;
float score;
float x;
float y;
float ran;
float a;
float b;
void setup(){
size(800,600);
background(0);
score = 0;
}
void draw(){
background(0);
text("score: "+score,600,20);
x = random(800);
y = random(600);
circle_(x,y);
if ( (abs(mouseX - x) <= 200) && (abs(mouseY - y) <= 200 )) { // algorithm for checking whether mouse inside the circle or not
score = score + 1;
}
}
void circle_(float x,float y){
delay(1000);
circle(x,y,50);
}
There are 2 problems here: first, you're checking 200 pixels where it should be 25 (as in 25 being half the diameter of the circle). But this is the easy one. The real issue is with the delay(1000); line.
That's the real pain.
It means that your program "sleeps" for about 1000/1001 seconds. While the mouse can go around the screen, this one just isn't listening. It's waiting.
You can track time in Processing with the millis() method. It gives you how many milliseconds have passed since you started running the sketch. I ninja coded you a couple lines to keep track of time and teleport the circle every 1 second. Here's the code:
float score;
float x;
float y;
int respawnCircle;
void setup() {
size(800, 600);
background(0);
score = 0;
}
void draw() {
background(0);
text("score: "+score, 600, 20);
if (millis() > respawnCircle) {
changeCircleCoordinates();
}
circle_(x, y);
if ((abs(mouseX - x) <= 25) && (abs(mouseY - y) <= 25 )) { // using 25 as it's half the circle's diameter
score = score + 1;
// if you want the circle to change place right when you get one point uncomment the next line
// changeCircleCoordinates();
}
}
void changeCircleCoordinates() {
respawnCircle = millis() + 1000;
x = random(800);
y = random(600);
}
void circle_(float x, float y) {
//delay(1000); // this is why your collision detection wasn't working: the program is sleeping for about 1000/1001 milliseconds... you have to be very lucky to be on target at just the right time
circle(x, y, 50);
}
Hope it helps. Have fun!
I have created a simple rendition of the classic Pong game on Android Studio for a college course. At this point, almost everything is ready to go, except for the fact that I created an unbeatable AI for the enemy paddle. I created the paddles and the ball with the default RectF class and change my AI paddle's position based on the ball's current position (I subtract/add by 65 because my paddles' lengths are 130 pixels and it centers the paddle compared to the ball). This essentially allows the enemy paddle to move at an infinite speed because it is matching the ball's speed/position (the ball speed increases with each new level). Here is that method:
public void AI(Paddle paddle) {
RectF paddleRect = paddle.getRect();
RectF ballRect = ball.getRect();
if (ballRect.left >= 65 && ballRect.right <= screenX - 65) {
paddleRect.left = (ballRect.left - 65);
paddleRect.right = (ballRect.right + 65);
}
if (ballRect.left < 65) {
paddleRect.left = 0;
paddleRect.right = 130;
}
if (ballRect.right > screenX - 65) {
paddleRect.left = screenX - 130;
paddleRect.right = screenX;
}
}
For reference, here are the relevant parts of my Paddle class:
public Paddle(float screenX, float screenY, float xPos, float yPos, int defaultSpeed){
length = 130;
height = 30;
paddleSpeed = defaultSpeed;
// Start paddle in the center of the screen
x = (screenX / 2) - 65;
xBound = screenX;
// Create the rectangle
rect = new RectF(x, yPos, x + length, yPos + height);
}
// Set the movement of the paddle if it is going left, right or nowhere
public void setMovementState(int state) {
paddleMoving = state;
}
// Updates paddles' position
public void update(long fps){
if(x > 0 && paddleMoving == LEFT){
x = x - (paddleSpeed / fps);
}
if(x < (xBound - 130) && paddleMoving == RIGHT){
x = x + (paddleSpeed / fps);
}
rect.left = x;
rect.right = x + length;
}
The fps in the update(long fps) method above is passed through from the run() method in my View class:
public void run() {
while (playing) {
// Capture the current time in milliseconds
startTime = System.currentTimeMillis();
// Update & draw the frame
if (!paused) {
onUpdate();
}
draw();
// Calculate the fps this frame
thisTime = System.currentTimeMillis() - startTime;
if (thisTime >= 1) {
fps = 1000 / thisTime;
}
}
}
My paddles and ball constantly update in my onUpdate() method in the View class.
public void onUpdate() {
// Update objects' positions
paddle1.update(fps);
ball.update(fps);
AI(paddle2);
}
How can I attach a speed limit to my AI paddle using the paddle speed I already define for each new paddle? I've already tried modifying the AI(Paddle paddle) method to incorporate +/- (paddleSpeed / fps) and it didn't affect the paddle seemingly at all. Maybe I just implemented it wrong, but any help would be fantastic!
To make the AI move the paddle at a steady rate rather than jumping to the correct spot, just try to make the middle of the paddle line up with the middle of the ball:
public void AI(Paddle paddle) {
RectF paddleRect = paddle.getRect();
RectF ballRect = ball.getRect();
float ballCenter = (ballRect.left + ballRect.right) / 2;
float paddleCenter = (paddleRect.left + paddleRect.right) / 2;
if (ballCenter < paddleCenter) {
setMovementState(LEFT);
}
else {
setMovementState(RIGHT);
}
}
and then after you call AI(paddle2) inside of onUpdate, call paddle2.update(fps). This way you aren't repeating yourself with the drawing code. You will notice that the AI paddle may not do perfectly if the ball is much faster than the paddle. In this case you can use math to anticipate where the ball will end up and work on getting there.
Ok so I have been try to get this ball to bounce naturally for a few weeks now and can't seem to get it right. The program should allow the user to input a set amount of gravity and then have the ball bounce according to that amount. It works for the first few bounces but stopping the ball is the problem. I have to deliberately set its movement to 0 or else it will endlessly bounce in place but not move on the x-axis. This issue only happens when the gravity is set to 15, other amount and things really go bad. The ball will bounce naturally but then keep rolling on x-axis forever. I've never taken a physics class so the issue is probably in the physics code. Anyone know where the issue is?
Here is the code my code-
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.util.Random;
import javax.swing.JOptionPane;
//key stuff
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
public class StartingPoint extends Applet implements Runnable{
//key press
private static boolean wPressed = false;
public static boolean isWPressed() {
synchronized (StartingPoint.class) {
return wPressed;
}
}
//for position of circle
int x = 0;
int y= 0;
//for position change
double dx = 2;
double dy = 2;
//for circle size
int rad = 11;
//image for update()
private Image i;
private Graphics gTwo;
//Physics
double grav = 15;
double engloss= .65;
double tc = .2;
double friction = .9;
#Override
public void init() {
// sets window size
setSize(800,600);
}
#Override
public void start() {
//"this" refers to the implemented run method
Thread threadOne = new Thread(this);
//this goes to run()
threadOne.start();
}
#Override
public void run() {
String input = JOptionPane.showInputDialog( "How much gravity?" );
grav= Double.parseDouble(input);
// sets frame rate
while (true){
//makes sure it doesn't go off screen x wise
//right side
if (x + dx > this.getWidth() - rad -1){
x= this.getWidth() -rad -1; //blocks it from moving past boundary
dx = -dx; //Reveres it
}
//left side
else if (x + dx < 1 + rad){
x= 1+rad; //ball bounces from the center so it adjusts for this by adding one and rad to pad out the radius of the ball plus one pixel.
dx = -dx; //Inverters its movement so it will bounce
}
//makes the ball move
else{
x += dx; // if its not hitting anything it keeps adding dx to x so it will move.
}
//friction
if(y == this.getHeight()-rad -1){
dx *= friction; //every time the ball hits the bottom dx is decreased by 10% by multiplying by .9
//Keeps it from micro bouncing for ever
if (Math.abs(dy) < 4){ // if the speed of y (dy) is less than .4 it is set to 0
dy= 0;
}
/**if (Math.abs(dx) < .00000000000000000001){ // if the speed of x (dx) is less than .00000000000000000001 it is set to 0, this value doesn't seem to matter
dx = 0;
}**/
}
//makes sure it doesn't go off screen y wise
//down
if (y > this.getHeight() - rad -0){ // TODO Check how getHieght is measured.
y= this.getHeight() -rad -0;
//makes ball loose speed.
dy *= engloss;
dy = -dy;
}
else {
//velocity
// tc makes grav smaller. Total of which is added to dy. To increase velocity as the ball goes down.
dy += grav *tc;
//gravity
//new dy is decreased by tc + .5 multiplied by gravity and tc squared. This makes the ball bounce lower every time based on its speed
y += dy*tc + .5*grav*tc*tc;
}
//frame rate
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//end frame rate
}
#Override
public void stop() {
}
#Override
public void destroy() {
}
#Override
public void update(Graphics g) {
//keeps it from flickering... don't know how though
if(i == null){
i = createImage(this.getSize().width, this.getSize().height);
gTwo = i.getGraphics();
}
gTwo.setColor(getBackground());
gTwo.fillRect(0, 0, this.getSize().width, this.getSize().height);
gTwo.setColor(getForeground());
paint(gTwo);
g.drawImage(i, 0, 0, this);
//do some thing with setDoubleBuffered
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLUE);
g.fillOval(x-rad, y-rad, rad*2, rad*2);
}
}
Synopsis
Well, I'm making a little top-down JRPG and today I was like 'Yeah, I'm gonna bust out this whole map collision thing!'. I failed.
Problem
So I went on the internet and looked up 'LibGDX Tiled Map Collision Detection' and found a really neat post about Map Objects so I added in a map object layer and did all that biz and came out with this little method to ensure the player can move freely around the map but at the same time can't exit it but each time I've tried it ends up with a horrible result such as the player moving off the screen. The latest error is that the player gets stuck doing a walk animation and can't move anywhere else!
Code
package com.darkbyte.games.tfa.game.entity.entities;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.math.Rectangle;
import com.darkbyte.games.tfa.game.entity.Entity;
import com.darkbyte.games.tfa.game.entity.SpriteSheet;
import com.darkbyte.games.tfa.game.world.map.MapManager;
import com.darkbyte.games.tfa.render.Batch;
import com.darkbyte.games.tfa.render.Camera;
public class Player extends Entity {
// The constructor for the player class
public Player(String name, SpriteSheet spriteSheet) {
super(name, spriteSheet);
direction = Direction.DOWN;
collisionBox = new Rectangle(x, y, 64, 64);
}
// A flag to see if the player is moving
private boolean isMoving;
// The variable that holds the state time
private float stateTime;
// The player's walking animations
private Animation[] walkAnimations = {
spriteSheet.getAnimation(8, 8, 1 / 16f),
spriteSheet.getAnimation(9, 8, 1 / 16f),
spriteSheet.getAnimation(10, 8, 1 / 16f),
spriteSheet.getAnimation(11, 8, 1 / 16f) };
// The player's static frames
private TextureRegion[] staticFrames = {
spriteSheet.getTexture(8, 0),
spriteSheet.getTexture(9, 0),
spriteSheet.getTexture(10, 0),
spriteSheet.getTexture(11, 0) };
// The render code for the player
#Override
public void render() {
// Makes the camera follow the player
Camera.setCameraPosition(x, y);
Batch.getGameBatch().setProjectionMatrix(Camera.getCamera().combined);
// Updates the state time
stateTime += Gdx.graphics.getDeltaTime();
// Gets the player's direction, if the player's moving, it sets the
// current frame to the frame that would be played at the current moment
// based on the state time
// If the player isn't moving, it sets the current frame to the static
// frame associated to the direction
switch (direction) {
case UP:
if(isMoving) {
currentFrame = walkAnimations[0].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[0];
break;
case LEFT:
if(isMoving) {
currentFrame = walkAnimations[1].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[1];
break;
case DOWN:
if(isMoving) {
currentFrame = walkAnimations[2].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[2];
break;
case RIGHT:
if(isMoving) {
currentFrame = walkAnimations[3].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[3];
break;
}
}
// The tick code for the player
#Override
public void tick() {
// The object to represent the bounds of the land on the map
RectangleMapObject land = (RectangleMapObject) MapManager.getCurrentMap().getMap().getLayers().get("collision").getObjects().get("land");
// Checks if the player is within the bounds of the map
if(land.getRectangle().contains(collisionBox)) {
// If the player is moving but the arrow keys aren't pressed, sets isMoving to false
isMoving = (isMoving && (Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)
|| Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)
|| Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)
|| Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)));
// Checks to see if the arrow / WASD keys are pressed and moves the
// player in the correct direction at the speed of 1.5 pixels/tick
// (45/second)
// It also sets the players state to moving and corresponds it's
// direction to the key pressed
// Doesn't move if opposing keys are pressed
if(Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)) {
if(!(Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN))) {
direction = Direction.UP;
y += 1.5f;
isMoving = true;
}
}
if(Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)) {
if(!(Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT))) {
direction = Direction.LEFT;
isMoving = true;
x -= 1.5f;
}
}
if(Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)) {
if(!(Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP))) {
direction = Direction.DOWN;
y -= 1.5f;
isMoving = true;
}
}
if(Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)) {
if(!(Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT))) {
direction = Direction.RIGHT;
x += 1.5f;
isMoving = true;
}
}
} else {
if(!isMoving) {
// If the player's just spawned puts the player to the map's spawn point
x = MapManager.getCurrentMap().getPlayerSpawnX();
y = MapManager.getCurrentMap().getPlayerSpawnY();
} else { // If not, it just moves them back till they're no longer out of the map
if(x > (land.getRectangle().getX() + land.getRectangle().getWidth())) x -= 1.5;
if(y > (land.getRectangle().getY() + land.getRectangle().getHeight())) y -= 1.5;
}
}
// Synchronises the collision box with the player's x and y position
collisionBox.x = x;
collisionBox.y = y;
}
// Returns if the player is moving
public boolean isMoving() {
return isMoving;
}
}
Can you guys make it so that when he reaches the border that he stops but he can still keep moving in other directions instead of staying static!
Thanks for reading!
At the moment it sounds you just copy/pasted it and you need to familiarize yourself with it first. If you don't know what it does then you should learn or stop the project imho.
Anyway, from what I can tell it's just a player class that handles the animation frames based on which direction it is moving. Nothing to do with collision detection at all. It does update some kind of collisionBox but functionality for this is handled elsewhere, perhaps in the parent class Entity?
My guess is that this is a tile map and units are restricted to the grid. It's pretty easy to detect if A tile exists or not.
private boolean tileExists(int tileX, int tileY, tile[][] map)
{
return tileX >= 0 && tileY >= 0 &&
tileX < map.length && tileY < map[0].length;
}
Now whenever a entity requests a move you should check if the destination is within the map bounds.
private void moveRequest(int destinationX, int destinationY, Tile[][] map)
{
//Just return if the tile is outside of the map
if (!tileExists(destinationX, destinationY, map) return;
//Same goes for your other checks...
//Return if the tile is not walkable
if (!tileIsWalkable(destinationX, destinationY, map) return;
//Return if the tile is already occupied
if (tileIsOccupied(destinationX, destinationY, otherEntities) return;
//etc..
//Now the move is valid and you can set it's state to moving in that direction.
}
Tile maps are not very hard to understand. I will make an attempt to give you some better insight into tile maps. You have a 2D array where you store your tiles in. Tiles have a width and a height and from that you can make your own tile engine:
//Find out which tiles to draw based on the camera position and viewport size.
int startX = (int)(camera.position.x - camera.viewportWidth / 2) / tileWidth;
int startY = (int)(camera.position.y - camera.viewportHeight / 2) / tileHeight;
int endX = (int)(startX + camera.viewportWidth / tileWidth) + 1;
int endY = (int)(startY + camera.viewportHeight / tileHeight) + 1;
//Loop using this data as boundaries
for (int y = startY; y < endY; y++)
{
for (int x = startX; x < endX; x++)
{
//If out of bounds continue to next tile.
if (!tileExists(x, y, map) continue;
//Now all we need to draw the on screen tiles properly:
//x == tile position x in array
//y == tile position y in array
//World position of this tile:
//worldX = x * tileWidth;
//worldY = y * tileHeight;
//Let's draw:
batch.draw(map[x][y].getTexture, worldX, worldY,
tileWidth, tileHeight)
}
}
There really is no magic involved here at all. Drawing only what is on screen like in the above example is very important for larger maps. Other then that you should draw thing in the back first. You have several options to do this, the easiest but least versatile is just a separate the ground from the objects that can obscure things and draw this later.
Characters, creatures or other entities can just use a world position and be easily converted back to tile position.
tileX = worldX / tileWidth;
tileY = worldY / tileHeight;
So if you want to move something with the world position calculate it's tile position first using the aforementioned method. Then lookup if this tile is valid to move to. Then block that tile for other and move to it.
So, I'm trying to make a game in LWJGL and it seems to work fine for me. Although, I ran into some issues in moving my entities around on the screen. I want to make it go from one point to another, at the same speed. Also, I'm animating my sprite according to the direction the entity is moving.
But! I have some issues:
1# It flickers because the movement is defined a modifier: delta (to make smooth movement defined by the FPS). Actually, it never really reaches it's point (because it recalculates and never hits the position). How can I solve this?
2# When 2 players join the same server, my character on the fastest computer runs faster. I think it's because of the FPS, how can that be solved?
private String name;
private float positionx,positiony; // Current
private int targetx,targety; // Target
private int dx, dy; // Direction
private int pointx, pointy; // Direction
private float speed;
private Sprite sprite;
public Entity(String name, int positionx, int positiony, Sprite sprite){
this.name = name;
this.speed = 0.1f;
this.positionx = 720;
this.positiony = 450;
this.targetx = 1000; // fix this
this.targety = 10; // this for testing.
this.sprite = sprite;
this.dx = 0;
this.dy = 0;
}
//double distance = Math.sqrt((vx * vx) + (vy * vy));
public void move(long delta){
if(positionx < targetx){
dx = 1;
pointx = 1;
}else if(positionx > targetx){
dx = -1;
pointx = -1;
}else{
dx = 0;
}
if(positiony < targety){
dy = 1;
pointy = 1;
}else if(positiony > targety){
dy = -1;
pointy = -1;
}else{
dy = 0;
}
//Set animations:
if(positionx==targetx && positiony==targety){
if(pointx<0){
sprite.setAnimation(5, 2, 100); // Standing left
}else if(pointx>0){
sprite.setAnimation(6, 2, 100); // Standing right
}else if(pointy<0){
sprite.setAnimation(7, 2, 100); // Standing up
}else if(pointy>0){
sprite.setAnimation(4, 2, 100); // Standing down
}
}else{
if(pointx<0){
sprite.setAnimation(1, 2, 100); // Walking left
}else if(pointx>0){
sprite.setAnimation(2, 2, 100); // Walking right
}else if(pointy<0){
sprite.setAnimation(3, 2, 100); // Walking up
}else if(pointy>0){
sprite.setAnimation(0, 2, 100); // Walking down
}
}
//movement here.
positionx += dx*delta*speed;
positiony += dy*delta*speed;
System.out.println(dx*delta*speed);
sprite.setPosition((int)positionx, (int)positiony);
}
1# It flickers because the movement is defined a modifier: delta (to make smooth movement defined by the FPS). Actually, it never really reaches it's point (because it recalculates and never hits the position). How can I solve this?
If you store point A and point B between which it moves, you can set a time interval. Each time interval a set distance will be travelled and if at one iteration the object goes too far you can set its coordinates for point B. This can be easily done with a Timer. That way, after a certain amount of time, it will be on your specified position.
2# When 2 players join the same server, my character on the fastest computer runs faster. I think it's because of the FPS, how can that be solved?
Same answer as question #1, if you use a Timer. Each player will move at the same speed (because the elapsed time is the same for each gamer).
Bottom line:
fps is variable, while elapsed time is the same for everyone.