This is my first attempt in game development. I just started experimenting libgdx and understanding the different aspects of game programming. I looked at the sample projects, i can understand the overall architecture of the libgdx game. But to get hold of the basics of game dynamics, i started playing with low level stuff like how to draw simple shapes, how to move them, how to handle collision like that.
So i planned to write a dead simple android game(Its not even a game for sure). This is the idea
1. Create random shapes and make it fly (move)
2. When user touches the shape, it ll explode or hide or play simple animation
3. Has to show Hit & Miss count
Initially i thought of going to try libgdx stage & actor concept, but ruled out that to do without the scene API. And I started this to experiment with different aspects of basic gaming and better understand the concepts behind libgdx. So i made this simple app, i am able to make objects fall random.
public class A1GameScreen implements Screen {
OrthographicCamera camera;
ShapeRenderer debugRenderer = new ShapeRenderer();
Array<Rectangle> boxes;
long lastFlew;
int fliesCaught;
A1GameScreen(){
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
boxes=new Array<Rectangle>();
throwboxes();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
debugRenderer.setProjectionMatrix(camera.combined);
debugRenderer.begin(ShapeType.Line);
for (Rectangle fly : boxes) {
debugRenderer.rect(fly.x, fly.y, fly.width, fly.height);
}
debugRenderer.end();
//Handle the user input
if (Gdx.input.isTouched()){
hit(Gdx.input.getX(),Gdx.input.getY());
}
if (TimeUtils.nanoTime() - lastFlew > 1000000000)
throwboxes();
Iterator<Rectangle> iter = boxes.iterator();
while (iter.hasNext()) {
Rectangle fly = iter.next();
fly.x -= 2;
if (fly.x + 32 < 0)
iter.remove();
}
}
//Method to create flies at random interval
private void throwBoxes(){
Rectangle fly = new Rectangle();
fly.y = MathUtils.random(0, 480 - 32);
fly.x = 800;
fly.width = 32;
fly.height = 32;
boxes.add(fly);
lastFlew = TimeUtils.nanoTime();
}
private boolean hit (float x, float y) {
boolean found=false;
for (Rectangle fly : boxes) {
found = fly.contains(x,y);
if (found){
found = true;
fly.width=100;
break;
}
}
return found;
}
}
But i couldn't able to find out the touched item from the falling objects. This is what i am doing to find out whether the box is in touched range
Loop through all the boxes in the array
Check if the touch co-ordinates falls within the box co-ordinates
I passed touch co-ordinates to contains method of the Rectangle (Box) to figure out that
something like this
for (Rectangle fly : boxes) {
found = fly.contains(x,y);
if (found){
found = true;
fly.width=100;
break;
}
}
But its not working. I think i figured the problem. Its
Box is moving 2px in x axis each frame, to make flying effect
But i am assuming, some frames has passed since the touch event. Thats why i am not getting the expected result
My questions are
How to solve this issue?
Whats the best way to detect collision in libgdx?
Update
I see lot of mismatch between the touch co-ordinates and box co-ordinates. None of the boxes in the touch range. Hows that possible. Below the sample trace
Touch coords: x-651.0 y-362.0
Fly coords: x-384.0 y-277.0
Fly coords: x-504.0 y-34.0
Fly coords: x-624.0 y-103.0
Fly coords: x-744.0 y-238.0
Touch coords: x-441.0 y-193.0
Fly coords: x-52.0 y-34.0
Fly coords: x-172.0 y-103.0
Fly coords: x-292.0 y-238.0
Fly coords: x-414.0 y-261.0
Fly coords: x-534.0 y-109.0
Fly coords: x-656.0 y-283.0
Fly coords: x-776.0 y-323.0
Touch coords: x-568.0 y-162.0
Fly coords: x-42.0 y-267.0
Fly coords: x-162.0 y-166.0
Fly coords: x-282.0 y-266.0
Fly coords: x-404.0 y-52.0
Fly coords: x-526.0 y-296.0
Fly coords: x-646.0 y-64.0
Fly coords: x-766.0 y-16.0
public static boolean pointInRectangle (Rectangle r, float x, float y) {
return r.x <= x && r.x + r.width >= x && r.y <= y && r.y + r.height >= y;
}
In your update-
if(pointInRectangle(flyRectangle, Gdx.input.getX(), Gdx.input.getY())){
// Do whatever you want to do with the rectangle. maybe register them for effect
}
You can also look into Intersector class.
Now for collision, if your game is fast-paced, with lots of enemies moving around that the player can collide with, sooner or later you will use a box2d type library because if the movement speed is high, you might not get any collision callback. Things might go through each other. You can try predicting the collision before it happens using the velocity and deltaTime, but it's still not going to be enough and you will end up reinventing the wheel.
Mario's SuperJumper is a great demo to start libGDX. Try it.
EDIT:
Have an instance member-
Vector3 touchPoint;
On create-
touchPoint = new Vector3();
On update-
camera.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
if (Gdx.input.justTouched()) {
if (pointInRectangle(rectangle, touchPoint.x, touchPoint.y)) {
}
}
Please take note of the coordinate system in libGDX. For testing, create one rectangle on screen. On click, print/debug the coordinates of both the rectangle and touchPoint.
I've solved the problem by making an invisible rectangle which will follow the tap location and I made an if statement checking for overlapping of the invisible rectangle and checking for if the screen was just tapped.
Here is the code:
if(Gdx.input.isTouched()) {
Vector3 pointerPos = new Vector3();
pointerPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
cam.unproject(pointerPos);
touchPos.x = pointerPos.x /*+ 64 / 2*/;
touchPos.y = pointerPos.y /*+ 64 / 2*/;
}
Iterator<Rectangle> iter = raindrops.iterator();
while(iter.hasNext()) {
Rectangle raindrop = iter.next();
raindrop.y -= 300 * Gdx.graphics.getDeltaTime();
if(raindrop.y + 64 < 0) {
iter.remove();
}
if(raindrop.overlaps(touchPos) && Gdx.input.justTouched()) {
iter.remove();
dropSound.play();
}
all of this code is in the render method.
P.S: Change raindrops to the fly objects you want
Related
I have tried to create NPC character that can "see" the player by using cones of vision.
The NPC will rotate back and forth at all times.
My problem is that the arc has a generic and unchanging position, but when its drawn to the screen it looks correct.
[Screenshots of the collisions in action][1]
[GitHub link for java files][2]
I'm using Arc2D to draw the shape like this in my NPC class
// Update the shapes used in the npc
rect.setRect(x, y, w, h);
ellipse.setFrame(rect);
visionArc.setArcByCenter(cx, cy, visionDistance, visionAngle, visionAngle * 2, Arc2D.PIE);
/ CenterX, CenterY (of the npc),
/ the distance from the arc to the npc
/ a constant value around 45 degrees and a constant value around 90 degress (to make a pie shape)
I've tried multiplying the position and the angles by the sin and cosine of the NPC's current angle
something like these
visionArc.setArcByCenter(cx * (Math.cos(Math.toRadians(angle))), cy (Math.sin(Math.toRadians(angle)), visionDistance, visionAngle, visionAngle * 2, Arc2D.PIE);
or
visionArc.setArcByCenter(cx, cy, visionDistance, visionAngle - angle, (visionAngle + angle) * 2, Arc2D.PIE);
or
visionArc.setArcByCenter(cx, cy, visionDistance, visionAngle * (Math.cos(Math.toRadians(angle))), visionAngle * 2, Arc2D.PIE);
I've tried a lot but can't seem to find what works. Making the vision angles not constant makes an arc that expands and contracts, and multiplying the position by the sin or cosine of the angle will make the arc fly around the screen, which doesn't really work either.
This is the function that draws the given NPC
public void drawNPC(NPC npc, Graphics2D g2, AffineTransform old) {
// translate to the position of the npc and rotate
AffineTransform npcTransform = AffineTransform.getRotateInstance(Math.toRadians(npc.angle), npc.x, npc.y);
// Translate back a few units to keep the npc rotating about its own center
// point
npcTransform.translate(-npc.halfWidth, -npc.halfHeight);
g2.setTransform(npcTransform);
// g2.draw(npc.rect); //<-- show bounding box if you want
g2.setColor(npc.outlineColor);
g2.draw(npc.visionArc);
g2.setColor(Color.BLACK);
g2.draw(npc.ellipse);
g2.setTransform(old);
}
This is my collision detection algorithim - NPC is a superclass to ninja (Shorter range, higher peripheral)
public void checkNinjas(Level level) {
for (int i = 0; i < level.ninjas.size(); i++) {
Ninja ninja = level.ninjas.get(i);
playerRect = level.player.rect;
// Check collision
if (playerRect.getBounds2D().intersects(ninja.visionArc.getBounds2D())) {
// Create an area of the object for greater precision
Area area = new Area(playerRect);
area.intersect(new Area(ninja.visionArc));
// After checking if the area intersects a second time make the NPC "See" the player
if (!area.isEmpty()) {
ninja.seesPlayer = true;
}
else {
ninja.seesPlayer = false;
}
}
}
}
Can you help me correct the actual positions of the arcs for my collision detection? I have tried creating new shapes so I can have one to do math on and one to draw to the screen but I scrapped that and am starting again from here.
[1]: https://i.stack.imgur.com/rUvTM.png
[2]: https://github.com/ShadowDraco/ArcCollisionDetection
After a few days of coding and learning and testing new ideas I came back to this program and implemented the collision detection using my original idea (ray casting) and have created the equivalent with rays!
Screenshot of the new product
Github link to the project that taught me the solution
Here's the new math
public void setRays() {
for (int i = 0; i < rays.length; i++) {
double rayStartAngleX = Math.sin(Math.toRadians((startAngle - angle) + i));
double rayStartAngleY = Math.cos(Math.toRadians((startAngle - angle) + i));
rays[i].setLine(cx, cy, cx + visionDistance * rayStartAngleX, cy + visionDistance * rayStartAngleY);
}
}
Here is a link the the program I started after I asked this question and moved on to learn more, and an image to what the new product looks like
(The original github page has been updated with a new branch :) I'm learning git hub right now too
I do not believe that using Arc2D in the way I intended is possible, however there is .setArcByTangent method, it may be possible to use that but I wasn't going to get into that. Rays are cooler.
I know there are quite some questions (and answers) on this topic, but they all have different solutions, and none of them seems to be working in my case.
I'm developing a small test project with libGDX, in which I tried to add a simple tilemap. I created the tilemap using Tiled, which seems to be working quite good, except for the texture bleeding, that causes black lines (the background color) to appear between the tiles sometimes.
What I've tried so far:
I read several SO-questions, tutorials and forum posts, and tried almost all of the solutions, but I just don't seem to get this working. Most of the answers said that I would need a padding between the tiles, but this doesn't seem to fix it. I also tried loading the tilemap with different parameters (e.g. to use the Nearest filter when loading them) or rounding the camera's position to prevent rounding problems, but this did even make it worse.
My current setup:
You can find the whole project on GitHub. The branch is called 'tile_map_scaling'
At the moment I'm using a tileset that is made of this tile-picture:
It has two pixels of space between every tile, to use as padding and margin.
My Tiled tileset settings look like this:
I use two pixels of margin and spacing, to (try to) prevent the bleeding here.
Most of the time it is rendered just fine, but still sometimes there are these lines between the tiles like in this picture (sometimes they seem to appear only on a part of the map):
I'm currently loading the tile map into the asset manager without any parameters:
public void load() {
AssetManager manager = new AssetManager();
manager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
manager.setErrorListener(this);
manager.load("map/map.tmx", TiledMap.class, new AssetLoaderParameters());
}
... and use it like this:
public class GameScreen {
public static final float WORLD_TO_SCREEN = 4.0f;
public static final float SCENE_WIDTH = 1280f;
public static final float SCENE_HEIGHT = 720f;
//...
private Viewport viewport;
private OrthographicCamera camera;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
public GameScreen() {
camera = new OrthographicCamera();
viewport = new FitViewport(SCENE_WIDTH, SCENE_HEIGHT, camera);
map = assetManager.get("map/map.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
}
#Override
public void render(float delta) {
//clear the screen (with a black screen)
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
moveCamera(delta);
renderer.setView(camera);
renderer.render();
//... draw the player, some debug graphics, a hud, ...
moveCameraToPlayer();
}
private void moveCamera(float delta) {
if (Gdx.input.isKeyPressed(Keys.LEFT)) {
camera.position.x -= CAMERA_SPEED * delta;
}
else if (Gdx.input.isKeyPressed(Keys.RIGHT)) {
camera.position.x += CAMERA_SPEED * delta;
}
// ...
//update the camera to re-calculate the matrices
camera.update();
}
private void moveCameraToPlayer() {
Vector2 dwarfPosition = dwarf.getPosition();
//movement in positive X and Y direction
float deltaX = camera.position.x - dwarfPosition.x;
float deltaY = camera.position.y - dwarfPosition.y;
float movementXPos = deltaX - MOVEMENT_RANGE_X;
float movementYPos = deltaY - MOVEMENT_RANGE_Y;
//movement in negative X and Y direction
deltaX = dwarfPosition.x - camera.position.x;
deltaY = dwarfPosition.y - camera.position.y;
float movementXNeg = deltaX - MOVEMENT_RANGE_X;
float movementYNeg = deltaY - MOVEMENT_RANGE_Y;
camera.position.x -= Math.max(movementXPos, 0);
camera.position.y -= Math.max(movementYPos, 0);
camera.position.x += Math.max(movementXNeg, 0);
camera.position.y += Math.max(movementYNeg, 0);
camera.update();
}
// ... some other methods ...
}
The question:
I am using padding on the tilemap and also tried different loading parameters and rounding the camera position, but still I have this texture bleeding problem in my tilemap.
What am I missing? Or what am I doing wrong?
Any help on this would be great.
You need to pad the edges of your tiles in you tilesheet.
It looks like you've tried to do this but the padding is transparent, it needs to be of the color of the pixel it is padding.
So if you have an image like this (where each letter is a pixel and the tile size is one):
AB
CB
then padding it should look something like this
A B
AAABBB
A B
C C
CCCCCC
C C
The pixel being padded must be padded with a pixel of the same color.
(I'll try try create a pull request with a fix for your git-repo as well.)
As a little addition to bornander's answer, I created some python scripts, that do all the work to generate a tileset texture, that has the correct edge padding (that bornander explained in his answer) from a texture, that has no padding yet.
Just in case anyone can make use of it, it can be found on GitHub:
https://github.com/tfassbender/libGdxImageTools
There is also a npm package that can extrude the tiles. It was built for the Phaser JS game library, but you could still use it. https://github.com/sporadic-labs/tile-extruder
I am programming a game of sorts which would be kinda long to explain, but in short the player is an ellipse() and follows the mouse around, whilst the rect() is the obstacle that moves down the screen and needs to be dodged by the player, otherwise it's game over. There are multiple rect as I am using an ArrayList to store each obstacle object.
Currently, the player can just pass straight through the rect without anything happening to it. I have tried to solve it multiple times but it got extremely messy and I couldn't understand much due to being extremely new to Java (only 1 week of experience), so I have just placed the empty code below.
tldr; I need to figure out how to get an ellipse/rect collision to work (in its own method). I only have 1 week of Processing/Java experience. I've cut out most of the code that you don't need to look at, mainly just kept the variables used to define the shapes and the code for the shapes just in case you need that. Also, if possible could the collision method could be placed inside the Enemy Class.
Enemy Class (all the variables used to define the rect)
class Enemy {
int enemyNumber; // used to determine enemy type
//VARIABLES FOR ENEMY
boolean redEnemy = false; // determine enemy colour
color enemyColour = color(#B9B9E8); // sets default colour to blue
PVector position, velocity;
float xDist, yDist; // x and y distance for Bar
float smallCircleRad, bigCircleRad; // radius for circles
// **************************************************************************
Enemy() { //CONSTRUCTOR
position = new PVector(width/2, random(-300000, -250));
//println(position.y);
velocity = new PVector(0, 10);
smallCircleRad = 200;
bigCircleRad = 400;
xDist = width;
yDist = 200;
enemyNumber = int(random(1, 6));
}
// **************************************************************************
void redBar(float xPos, float yPos, float xDist, float yDist) {
redEnemy = true;
noStroke();
enemyColour = color(#E38585);
fill(enemyColour);
rect(xPos, yPos, xDist, yDist);
}
void blueBar(float xPos, float yPos, float xDist, float yDist) {
redEnemy = false;
noStroke();
enemyColour = color(#B9B9E8);
fill(enemyColour);
rect(xPos, yPos, xDist, yDist);
}
Player Class (all the variables used to define the ellipse)
class Player {
int r = 50; //player radius
float playerX = width/2; //starting x coordinate
float playerY = height/2+500; //starting y coordinate
float speed = 20; //player speed
float angle; //angle used to calculate trajectory for player
void playerChar() { //method for player model and general rules
stroke(10);
rectMode(CENTER);
fill(playerColour);
ellipse(playerX, playerY, r*2, r*2);
}
Make your life easier by treating the player as a rectangle instead of a circle. You can still draw them as a circle, but for collision detection, use a rectangle. This is called a bounding box and is very popular in collision detection.
Then you can use rectangle-rectangle collision detection, which is much simpler.
Some basic google searches return these results:
Axis-Aligned Bounding Box
What is the fastest way to work out 2D bounding box intersection?
Processing Collision Detection
If for some reason you absolutely need the player to be a circle when calculating the collision, then I'd start by googling something like "circle rectangle collision detection".
If you still can't get it figured out, please post a MCVE in a new question and we'll go from there. Good luck.
Using accelerometer my sprite image is moving left and right and if I touch my screen the sprite is moving to Y-axis.I want to make a collision detection between different sprites so that if the sprite pass through an object it will stop to hide in that object. I already watch a tutorial this https://www.youtube.com/watch?v=T1aN--vTqLc but nothings happen. What is the proper way to make collition detection? I don't know what's wrong with my coding.Any suggestion or much better tutorial Thank's and Advance
Here is my coding
private Rectangle rectangleCat;
private Rectangle rectangleShoes;
private float yPosition = -40;
Sprite
cat = new Texture(Gdx.files.internal("cat.png"));
catsprite = new Sprite(cat);
catX=300;
catY=0;
sprite_shoes = new Sprite(new Texture("equip/Shoes.png"));
sprite_shoes.setPosition(260,580);
rectangleShoes=new Rectangle(sprite_shoes.getX(),sprite_shoes.getY(),sprite_shoes.getWidth(),sprite_shoes.getHeight());
rectangleCat = new Rectangle(catsprite.getX(),catsprite.getY(),catsprite.getWidth(),catsprite.getHeight());
Render method
boolean isOverlaping = rectangleCat.overlaps(rectangleShoes);
if(!isOverlaping) {
System.out.println("not overlap");
yPosition = yPosition + (20 * delta);
}
My Sprite image and Object is not overlapping
Full source code http://pastebin.com/Dxfx9f65
First of all your sprite is not sharp Rectangle it's looks like polygon so you need to detect collision between two polygon.
Still if you want to detect collision between rectangle then get Bounding Rectangle of your sprite in render() method.
In render method
rectangleShoes=sprite_shoes.getBoundingRectangle();
rectangleCat=catsprite.getBoundingRectangle();
boolean isOverlaping = rectangleCat.overlaps(rectangleShoes);
if(!isOverlaping) {
System.out.println("not overlap");
yPosition = yPosition + (20 * delta);
}
I'm trying to create a simple Android game, a 2D action shooter which has 2 control sticks (circles) on the screen, the left one is movement control and the right one weapon control. Direction is being controlled by the position of your thumb relative to the circle’s center.
I've been following a tutorial on this site: http://www.kilobolt.com/day-7-creating-an-android-game-from-start-to-finish.html but it only gave me the base to work on. I have no programming experience so I'm quite lost now.
I got the movement working only on TOUCH_DOWN event, the hero moves to about where it should but to change direction I have to lift my thumb and touch the circle again. TOUCH_DRAGGED (or ACTION_MOVE) is broken because if I drag my finger across the circle the character moves really fast. I guess the problem is too many touch events are being handled, but I have no idea how to fix it.
How can I change this so that I can drag my thumb around the circle and the hero will change its direction instantly, and keep its speed constant all the time? Also the speed should be the same no matter how close or far from the center of the circle you touch.
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_DOWN || event.type == TouchEvent.TOUCH_DRAGGED) {
if (inBounds(event, 50, 300, 150, 150, 'c')) {
ctrl.setX(event.x);
ctrl.setY(event.y);
ctrl.direction();
hero.move(ctrl.getDirX(), ctrl.getDirY());
}
}
if (event.type == TouchEvent.TOUCH_UP) {
if (inBounds(event, 0, 0, 35, 35,'r')) {
pause();
}
hero.stopMove();
}
}
hero.update();
The movement: hero's speedX and speedY are added to hero's centerX and centerY on every hero.update() call.
public void move(float x, float y) {
speedX += x * MOVESPEED;
speedY += y * MOVESPEED;
}
This method that handles the x & y speed. Found it here at stackoverflow, and because touch_down event is working ok, I guess it's doing it's job. Although I feel it's not exactly how it's supposed to be. L_STICK_C is a constant with values of 100 and 350 (center of the circle).
public void direction() {
dir.x = x - L_STICK_C.x;
dir.y = y - L_STICK_C.y;
double hyp = Math.sqrt(dir.x * dir.x + dir.y * dir.y);
dir.x = (float) (dir.x / hyp);
dir.y = (float) (dir.y / hyp);
}
I suggest you look into some game programming tutorials. You usually would not move the character directly from the touch input. You'd set a game state variable once a game loop which would correspond to the position of your thumb inputs. Then you'd only update the hero once per game loop based on those inputs. This lets allows you to keep the game input control code, and hero code separate, and makes it re-usable for other parts of your game.
EDIT:
Based on your code, every time you drag your finger, you generate a bunch of dragged events. So you are adding onto your characters speed for each event. You should probably just be looking at the distance to center and x / y of the input on the last touch event, not all of them.