Pacman collision detection with varying character speeds? - java

I am programming a 2D, grid-based Pacman game. All the tiles are 8x8 in size. In-game, the map tiles are treated as 16x16, and the characters (Pacman and the ghosts) are treated as 32x32. In actuality, they are all pulled from a spritesheet of 8x8 tiles. I store positions as the center point of each character. Since the character tiles are bigger than the map tiles, the map is built in a way that requires the characters being able to "overlap" onto blocked tiles.
To deal with this set of problems, I created an invisible Rectangle and attached it to the character's position. Where the position is an (x,y) point, the Rectangle is a box surrounding that point. This rectangle is essentially 16x16 in-game, and is in the center of the character, which allows for the overlap necessary.
This works fine if you're working with 8px as the global movement speed, but I'd like to treat 8px as "100% speed" and have complete control over character speed with a double that is in the range [0,1). The positions are stored as double points, so on that level, this is fine. I read the positions back as integers, though, since I'm working with pixels.
So the question I ask is essentially "if this moves X amount of pixels to direction Y now, will my collision box be touching a blocked tile? But if you're moving 5px at a time, this eventually causes a very obvious issue. Say you're at x = 0, moving right. The tiles are 16x16 in-game, as stated before, and you have two of these open before the third, which is blocked. So you move, x = 5, x = 10, x = 15, x = 20, we just got to the 2nd tile, x = 25, x = 30, x = 35 now we're in the 3rd tile... but wait. We can't go there, because X = 35 collides. And unfortunately, we needed to turn and start moving down, but we can't, because now our Y-axis isn't aligned properly with the grid. Our X position needs to be 32, but can't.
My question for everyone here is, what are my options? What are some ideas or insights you have? I have a feeling I'm making it more difficult than I need to.

sounds like you have...
Why not give your "pac-man" sprite a velocity vector? The vector will describe not only the speed at which "pac-man" is traveling but in what direction, meaning you can see ahead.
"pac-man" should be calculating and ultimately making a decision based upon the following conversation..."hey, moving at this speed and in this direction..in so many seconds I'm going to hit a wall, when does that happen?". The seconds don't even have to be seconds...they could be "squares".
You would need a function which takes in the initial movement vector (direction and speed) which returns a coordinate of an X,Y point where "pac-man" must stop, where he cannot go further and must change direction (the center of a tile adjacent to a wall). Each time "pac-man" changes direction, run this calculation again...you do not need to keep checking if the next square is passable. If his direction hasn't changed and his speed is constant..you only need calculate once and let the coordinate system do the rest.
With this approach, square size and velocity is irrelevant...until "pac-man" hits or within his next movement exceeds the stopping point, continue to move along the vector.

Related

Android translated canvas collision of rectangles

im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.

libgdx 3d infinite scrolling floor

I'm making a 3D game, and looking at the best method to have a floor plane as part of the 3D. If you imagine those games like TempleRun, but no turns, where you are moving forwards and the floor is scrolling backwards (towards the user) infinitely.
I already have my 3D object moving around X axis suitably (on a fixed Z plane), but now looking at adding a background, floor, etc.
I've been reading on Decal and Plane but uncertain as to which would be the best approach. I'd have the same floor structure on each level, but with different textures. Does one offer more expandability in the future? Eg, slopes, hills, etc. Each floor structure (whether Decal or Plane) would be repeating endlessly, and I'd see if I can create a fog effect which makes the floor fade with distance. Also it would have a tileable texture (eg grass, tarmac, dirt) which would be repeating backwards.
Perhaps even a static structure, and simply move the texture backwards?
Any thoughts would be great, thanks.
I would say don't go with decals, as these don't react to libgdx's environments (lights, shadow, an so on). And a Plane is just some class that represents plane and can't be rendered at all.
Simples solution: go to blender or any other 3d editing tool of your choice create a plane and apply your tillable texture to it.
Export it as .fbx and convert it to .g3db (libGDX's format).
Load it into your game and and make a couple of copies of it (ModelInstances).
Place those on the floor one after another so that no gap appears and they all form a nice repeating ground.
As your character moves forward check its position on X axis (or whatever axis you want to move on) and if the position is greater than position of your last plane on the floor - some distance than update floor as follows:
Remove the first plane from ground and add it after the last plane that you have.
(Render everything with ModelBatch)
If you have enough of these planes the player wont notice them appearing in the distance. Also use fog to completely hide this transitioning of planes.
The same can be applied not only to planes but repeating hill or any other tillable 3d object.
You could have some Planes made with meshpartbuilder (Like explained here) or even a Model made with an Application like Blender.
As you can create many ModelInstances out of one Model and give them different Materials, you can use the same Model over and over again. So you could create a 4x4 meter (for example) big Model (it will only be 1 face) on the XZ-Plane. Next you create, lets say 10, ModelInstances out of it and add them to each other:
first Plane: x = 0-4m, y = 0-0, z = 0-4m
second Plane: x= 4-8m, y = 0-0, z = 0-4m
And so on. As soon as your character is at a X Position > 4, you can translate the ModelInstance firstPlane foreward to the end of the 10th plane. So its new x would be 44-48 meters.
As soon as you reach a new level or another ground or whatever you can simply change the Material of the ModelInstance.
For the background i would suggest to read something about SkyBoxes.
Hope i could help

Calculating every cartesian point in a moving cicrle

I have an array: int[][] lawn = new int[980][1280];
wich stores the values of the height of blades in the virtual “lawn”.
In my simulation i have a robot that goes around the lawn and cuts the blades.
My robot has the form of a circle with a diameter (rDiameter). The coordinate system is done with Double and my lawn is in Integer.
I have to develop an algorithm that puts to 0 all the cells touched by the robot when it moves around.
I have the start and end point of the movement, which are stored in a Line2D.Double form and I want to set on 0 all the cells touched by robot (image).
Any ideas?
(Here my previous question on the same argument every cartesian point in a circle
Break the problem in 3 parts. Part 1 is to set to 0 all points in a semi-circle. Part 2 is to set to 0 all points in a rectangle. Part 3 is to break the path into two semi-circles (at the ends) and a rectangle (joining them).
Note that the semi-circles and the rectangles have, in general, lines that are not axis aligned. There are plenty of references out there on rasterizing polygons and circles. You could look up Jack Bresenham's algorithms. Or you could flip open any classic computer graphics text.

Smooth grid movement

I'm working on a Java Bomberman clone, using a grid system, and I'm not really satisfied with the movement right now. When the player presses a movement key, the character starts to move (with 0.25 speed). The player loses the control, and the character keeps moving until it has moved a full tile. The player only regains control when the character gets to the center of the next tile.
This makes it's too "laggy". If I want to change direction now, I can't.
Maybe I could make the base of the character smaller than the size of the sprite, meaning I would have to check ahead of the corners to check if it was a valid move. Any thoughts?
Thanks!
I just played Bomberman a few minutes ago :)
You can move pretty smooth, there no grid calculations.
I haven't used Java that much. I use Flash a lot. Is the Grid for checking collisions ?
What is it for exactly ?
Would it make sense to have something like(I'll try to sketch it):
float vx,vy = 0;//velocity on x and y
Character bomberman
void keyDownHandler(KeyboardEventSomething event){
if(key is Left && ! Right ) vx -= .5;
else if(key is Right && !Left ) vx += .5;
//idem for Y axis
}
void keyUpHandler(KeyboardEventSomething event){
vx = vy = 0;
}
void updateLoop(){
bomberman.x += vx;
bomberman.y += vy;
}
I might be a bit off, because I'm not sure how much you want to clone Bomberman or not. What you're describing with the grid movement seems closer to hopmon
Don't disable user input. Ever. Constantly poll for it.
Have a Tick() or OnFrameEnter() function that does the following:
Poll the keyboard/joystick/whatever, and cache the last direction entered by the user.
Check the position of the character.
If the character is idle in the center of a grid square, set it's velocity in the proper direction and upate the movement one step, unless there's a wall/collision object in the way. Also clear out the last key press to some invalid value.
Else if the character is already moving, update the position of the character, checking for collision with a wall, or proximity to a direction changing node (intersection). If it collides with a wall, stop the character. If it's close to a direction changing node and can travel in the cached direction, change the direction and clear the cached direction. Else if the input direction is opposite the current direction (it's in a hallway and the player wants to reverse), reverse the direction and then clear the key press. This all assumes that the character should continue moving, always, until it hits a wall and stops. If you want the character to stop anywhere, a reverse direction key should simply stop it in place.
Caching the key press allows the player to preemptively change directions as the character approaches an intersection. This way the character doesn't have to wait to stop before moving on, and the player doesn't feel the game is unresponsive. Polling constantly lets the player reverse directions at any time, and makes direction changes at intersections seem faster.
You should be able to get rid of current sprite and load the new one exactly when you need it - i.e. if the character moved half way to the next tile and the player presses a key to return, cancel the sprite and load the new one starting at 0.5.
I guess it depends on how you want it to behave.
Say you are moving up, and you click right.. do you want it to stop moving up and go right?
I would store the previous grid location when you make a movement. that way if you click to move elsewhere you can hop backwards and change the movement direction..
Or if you are moving up and you click down... you could set the movement speed to be the opposite of what it is...
It is hard to answer with out knowing what you want it to behave like.
It sounds like you update the players position (start of the animation) by changing the grid cell in which its contained.
To be able to achieve the desired effect, the sprites render position should be independent of where the entity represented by that sprite is located on the grid. And allow the user to move inside that grid within a range of the cell's center without changing cells. If this range is not chosen correctly you may en up with the "doh! im in this (visually) cell but it says im in the future cell" problem, or the "my avatar is overlapping a wall".
Dont change the players cell until he is within a range (lets say 1/3 of the bounding sphere of the sprite) from the limits/borders of the cell that contains him. You would also have to modify the animation process for it to be interruptible.
This is independent of the degrees of liberty you give the player (like, it could only move up, down, left, right, and diagonals vs 360 degrees)
Another thing you should watch out for is, if the sprite is larger than the cell size. For instance, a Fat monster, or a Snake boss which spans across X cells but not necessarily in rectangular form.

How to represent a 400x400 window as a map in a Java game?

I'm building a pacman game. Basically, I want to have a map representation of this window consisting of blocks/tiles. Then as the pacman character/ghost moves i would change their position on the map to represent what's on the screen, and use that for collision detection etc.
How can I build this map, especially since the screen is made of x,y coordinates, so how can I correctly represent them in tiles/on this map?
I know it's tempting to start thinking of objects and interfaces but have you thought about a 2-dimensional array with each element representing 40 pixels or something? I don't remember pacman being pixel accurate when it came to collision, more a question of the direction each piece was moving in.
Generally you have an abstract representation that doesn't reference pixels as such (for example, maybe the Pac-Man maze is simply w units wide), and then you have a linear transformation (you know, y = mx + b) to carry the abstract representation to actual pixels.
To make it concrete, let's say that you want your abstract representation to be 100 units wide, and you want to render it as 400 pixels. Then the transformation is just scrn_x = 4 * x.
Kind of difficult to come up with this without writing it myself but.
First you'll need to create entity definitions that implement ICollidable. Entities would include ghosts, pacman, dots and powerups.
Each element in the map would contain, along with other information, a list of all present entities with a sort of "position" value for added precision. The ICollidable interface would include not only logic for determining which entities collide with one another (ghosts don't collide with dots for example.) but determining if they're in position to collide with one another. IE if pacman is entering a space from the right and a ghost is leaving that space from the left there's no collision. It will also help determine when exactly pacman has eaten a dot so that graphically it looks correct. IE if you destroy a dot right as pacman enters a space it's going to disappear before he even touches it graphically.
Your sprites such as pacman and the ghost are represented by positions (x,y). To determine if they collide with each other, use this psuedocode:
sprites = [ ... list of sprites ... ]
for i1=0 to len(sprites):
sprite1 = sprites[i1]
for i2 = i1+1 to len(sprites):
sprite2 = sprites[i2]
if (sprite1.x-sprite2.x)^2+(sprite1.y-sprite2.y)^2 < radius_of_sprites^2:
collide(sprite1, sprite2)
Note that this doesn't involve the map at all. We can check for collisions between pacman and the map separately. The key trick here is you divide the pixel coordinate of each of pacman's sides (top, bottom, left, right) and check for collisions. For example, if pacman is going to the right, we need to check the right edge for a collision:
pacman_tile_x = (pacman.x+tilesize/2)/tilesize # added tilesize/2 to check the middle of pacman
pacman_tile_y = pacman.y/tilesize + 1 # +1 because right edge is 1 tile to the right of the sprite's coordinate
if tile[pacman_tile_x][pacman_tile_y].is_a_wall:
... wall collide code ...
Now, if you have a huge number of sprites on the screen, you can optimize the sprite-to-sprite collision detection by storing which sprites exist on any particular tile in the map, and so you only have to check against sprites in adjacent tiles. But for a first pass and for this pacman game, it's probably not a necessary optimization.

Categories

Resources