Tile not being replaced when player collides with it - lua

When codeing a game i wanted the player to hit a specific tile and when hit the tile would be replaced with a dofferent tile with in the same tilemap.
This is the code:
pos = go.get_position()
x_tile = math.ceil(pos.x/16)
y_tile = math.ceil(pos.y/16)
tile = tilemap.get_tile("/level#Level_1", "level", x_tile, y_tile)
if not (self.last_tile == tile) then
if tile == 84 then
tilemap.set_tile("/level#Level_1", "level", x_tile, y_tile, 0)
end
self.last_tile = tile
end
When i play the project there are no errors
I'm trying to replace the tile with a clear tile so it looks like the tile has disappeared but when i tries the same idea but replacing it with a coloured tile it the coloured tile did'r replace but spawned ontop of the tile i wanted to replace? I have no idea why this is happening

Related

Zoom into scene using transition - Corona

Hey so I am looking for something similar to in tennis when players challenge a point and the video shows whether the ball was in or out by zooming in really really close to the moment when the ball lands to see whether a fraction was on the line.
I have experimented with using transitions with xScale and yScale but the results I get is strange, almost as if the objects have moved during zooming in. If there was a way to lock in position and then zoom, that would work. The second method I tried is putting the graphics into a display group and then scaling the group. This also results in weird behaviour where the whole group begins moving diagonally across the screen.
Please help as this is confusing me
cheers.
Objects which will scale:
cloud = display.newImageRect("cloud.png", 419,273)
cloud.anchorY = 0
cloud.anchorX = 0.5
cloud.alpha = 1
cloud.x = display.contentCenterX
cloud.y = display.contentCenterY + 250
physics.addBody(cloud, {isSensor=true})
star = display.newImageRect("Star.png", 78,72)
star.anchorY = 0
star.anchorX = 0.5
star.alpha = 1
star.name = "Star"
physics.addBody(star, {isSensor=true})
star.x = display.contentCenterX
star.y = display.actualContentHeight - display.actualContentHeight - 100
Scale Function
function scale( event )
transition.to(star, {time=2000, xScale=1.5, yScale = 1.5})
transition.to(cloud, {time=2000, xScale=1.5, yScale=1.5})
end
When you scale an object, it may "move" due to its anchor position, which is the position of the object that is used to position it and also works as its 'anchor' during rotation or scale.
So, you have 2 options:
1) Set the anchor position (obj.anchorX = value , obj.anchorY = value ) to the one that will make your object stays in the position that you want;
2) During the transition, also change its x and y to compensate the moving.

Box2D: How to use b2ChainShape for a tile based map with squares

Im fighting here with the so called ghost collisions on a simple tile based map with a circle as player character.
When applying an impulse to the circle it first starts bouncing correctly, then sooner or later it bounces wrong (wrong angle).
Looking up on the internet i read about an issue in Box2D (i use iOS Swift with Box2d port for Swift).
Using b2ChainShape does not help, but it looks i misunderstood it. I also need to use the "prevVertex" and "nextVertex" properties to set up the ghost vertices.
But im confused. I have a simple map made up of boxes (simple square), all placed next to each other forming a closed room. Inside of it my circle i apply an impulse seeing the issue.
Now WHERE to place those ghost vertices for each square/box i placed on the view in order to solve this issue? Do i need to place ANY vertex close to the last and first vertice of chainShape or does it need to be one of the vertices of the next box to the current one? I dont understand. Box2D's manual does not explain where these ghost vertices coordinates are coming from.
Below you can see an image describing the problem.
Some code showing the physics parts for the walls and the circle:
First the wall part:
let bodyDef = b2BodyDef()
bodyDef.position = self.ptm_vec(node.position+self.offset)
let w = self.ptm(Constants.Config.wallsize)
let square = b2ChainShape()
var chains = [b2Vec2]()
chains.append(b2Vec2(-w/2,-w/2))
chains.append(b2Vec2(-w/2,w/2))
chains.append(b2Vec2(w/2,w/2))
chains.append(b2Vec2(w/2,-w/2))
square.createLoop(vertices: chains)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = square
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Wall
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Player
let wallBody = self.world.createBody(bodyDef)
wallBody.createFixture(fixtureDef)
The circle part:
let bodyDef = b2BodyDef()
bodyDef.type = b2BodyType.dynamicBody
bodyDef.position = self.ptm_vec(node.position+self.offset)
let circle = b2CircleShape()
circle.radius = self.ptm(Constants.Config.playersize)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = circle
fixtureDef.density = 0.3
fixtureDef.friction = 0
fixtureDef.restitution = 1.0
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Player
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Wall
let ballBody = self.world.createBody(bodyDef)
ballBody.linearDamping = 0
ballBody.angularDamping = 0
ballBody.createFixture(fixtureDef)
Not sure that I know of a simple solution in the case that each tile can potentially have different physics.
If your walls are all horizontal and/or vertical, you could write a class to take a row of boxes, create a single edge or rectangle body, and then on collision calculate which box (a simple a < x < b test) should interact with the colliding object, and apply the physics appropriately, manually calling the OnCollision method that you would otherwise specify as the callback for each individual box.
Alternatively, to avoid the trouble of manually testing intersection with different boxes, you could still merge all common straight edge boxes into one edge body for accurate reflections. However, you would still retain the bodies for the individual boxes. Extend the boxes so that they overlap the edge.
Now here's the trick: all box collision handlers return false, but they toggle flags on the colliding object (turning flags on OnCollision, and off OnSeparation). The OnCollision method for the edge body then processes the collision based on which flags are set.
Just make sure that the colliding body always passes through a box before it can touch an edge. That should be straightforward.

2D physics / collision formula not working as intended

I have a 2D tile matrix (of walls for now) and for each wall I check if my player's next Rectangle (next as in where it will be in next frame) is colliding with that wall, and if it is, I want my player to stand right next to it, without going inside of it.
Here is the formula I came up with (this is just for left and right collision):
//*move entity
if (KState.Down(Keys.W)) en.AddForce(new Vector2(0, -10));
if (KState.Down(Keys.S)) en.AddForce(new Vector2(0, 10));
if (KState.Down(Keys.A)) en.AddForce(new Vector2(-10, 0));
if (KState.Down(Keys.D)) en.AddForce(new Vector2(10, 0));
foreach(Item i in map.Items)
{
//resolve left-right collision
if (en.NextBody(elapsedTime).Intersects(i.Body))
{
//check distance between top left corners
int distance = (int)Math.Abs(i.Position.X - en.Position.X);
//stop player in his horisontal movement
en.AddForce(new Vector2(-en.Force.X, 0));
//place player next to the wall his about to collide with
en.Position = new Vector2(en.Position.X - distance + i.Body.Width, en.Position.Y);
}
}
//stop player in place
if (KState.Clicked(Keys.Space)) en.AddForce(en.Force*-1);
en.Update(elapsedTime);
**
Which gave me this result (note that fps is not stable and that currently rectangles are squares 32x32):
Top line of text is players Rectangle, and bottom one is Rectangle of the wall that player collided with last.
Now, when the rocks (player) is moving to the left, I'm holding left key for some time, and when going to the right, I'm holding right key for some time.
Problem: As you can see in gif, when player's going left, he's moving 1 pixel to and from left wall. And when he's moving right, he bounces once, and then stays right next to the right wall. I don't want any bouncing but I don't know how to fix this in logic that I'm using.
Also, if you know good logic for how to resolve Rectangle collision so that they are not intersecting from any sides, I'd appriciate sharing it with me.
Edit 1: I managed to resolve collision to the right problem. Instead of the code above I've put
int sign = Math.Sign(i.Position.X - en.Position.X);
en.AddForce(new Vector2(-en.Force.X, 0));
//wall is right and player is left
if (sign > 0) en.Position = new Vector2(i.Body.Left - en.Body.Width, en.Position.Y);
//wall is left and player is right
if (sign < 0) en.Position = new Vector2(i.Body.Right, en.Position.Y);
but the problem with the left side collision is the same. I tried
if (sign < 0) en.Position = new Vector2(i.Body.Right + 1, en.Position.Y); and if (sign < 0) en.Position = new Vector2(i.Body.Right - 1, en.Position.Y); just in case, but the problem is the same (on "...-1..." case player gets stuck in wall).
Edit 2: As #paste requested, here is the code for NextBody(float elapsedTime) from player class.
public Rectangle NextBody(float elapsedTime)
{ return new Rectangle((int)(force.X * elapsedTime) + body.X, (int)(force.Y * elapsedTime) + body.Y, body.Width, body.Height); }
This is what's happening:
The first time the objects collide while the rocks are moving left, the algorithm works as it should. It sees that the objects are overlapping, it sets the force to Vector2.Zero, and it moves the en so that it is touching the item's right side. Good. Your object is stopped and in the right place.
What happens in the next frame is where things go wrong. You set up your force vector, and then call NextBody(). Let's just look at the X-coordinate. It gets set to:
(int)(force.X * elapsedTime) + body.X
What does this evaluate to? force.X is non-zero, and elapsedTime is also non-zero, but they're less than 1, so when they get converted to int, the result is zero. Therefore, your body is in the same place as it was before, which means the Rectangles do not overlap. This means your collision response code gets skipped and your force vector is still not zero!
Then, further down, you call your player's Update() method. I'm guessing that in that code you update the player's Position and Body. But since force is not zero, and you are using a Vector2 for Position, the x-coordinate will end up being something like 31.841304... instead of 32. If you use that number to calculate the new Body and use it in your Draw method, you'll end up drawing it at x = 31. The next time you check, it'll detect a collision, and the player will bounce out again.
There are a number of ways to fix this. What I do in my collision code is to actually move the objects first and keep a record of where they were in the previous frame. That way, the last adjustment to their position is when they are moved out of the collision area.

How to turn off anti aliasing on a sprite kit node's texture

I'm currently trying to put a test game together in Sprite Kit. I have some code that creates a patch of ground using a pair of PNG images with dimensions 200 * 572.
let textures = [SKTexture(imageNamed: "GrassAni1"), SKTexture(imageNamed: "GrassAni2")]
for (var i = 0; i < 10; i += 1) {
let chunk = SKSpriteNode(texture: textures[0])
chunk.position = CGPointMake(CGFloat(200 * i), 0)
let animate = SKAction.animateWithTextures(textures, timePerFrame: 1)
chunk.runAction(SKAction.repeatActionForever(animate))
//boilerplate physics body codeā€¦
self.addChild(hero)
}
Enter my problem. Here is an up-close of my sprite in the Xcode file viewer:
And here's what it looks like when the game is running:
The in-game sprite appears to be anti-aliased and as a result looks fuzzy. How do I prevent this and make the game look as sharp as the original images?
You will need to change the filteringMode on your SKTexture objects to SKTextureFilteringMode.Nearest.
Then as long as your node is positioned on pixel boundaries, it should be drawn as expected.

How to attach a new sprite to a moving sprite?

I'm using SpriteKit for a game where there is a ball and a character. The character is moving in a line with SKAction and the user can move the ball by touch. When the ball and character makes contact, I'd like the ball to be attached to the character.
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == charMask && contact.bodyB.categoryBitMask == ballMask{
println("contact")
if contactMade {
let movingBall = contact.bodyB.node!.copy() as! SKSpriteNode
//this line of code doesn't affect anything no matter what coordinates i set it to
movingBall.position = contact.bodyA.node!.position
contact.bodyB.node!.removeFromParent()
contact.bodyA.node!.removeAllActions()
contact.bodyA.node!.addChild(movingBall)
}
}
}
The current issue is that when I do contact.bodyA.node!.addChild(ball) (character node), the ball gets attached to the far left side of the character instead of on the character and it seems setting movingball.position does not affect it. I've also tried doing addChild to the scene and although it adds the ball to the correct place, it doesn't move with the character without another SKAction. What did I do wrong/what can I do to fix it?
Also, instead of using 2 sprites like that, should I use separate sprites so that theres a character sprite without a ball, character sprite with a ball and the ball itself, then just change the node's texture when they contact?
as movingBall is to be a child of bodyA.node, it's position needs to be in bodyA.node's coordinate space. So if you gave it coordinates of (0,0) it'd be in the middle:
Replace:
movingBall.position = contact.bodyA.node!.position
with
movingBall.position = CGPointZero
and see how that looks. the ball should be positioned directly on top of bodyA.node.

Resources