Iphone - CGPointIntersectsRect Collision Problem? - iphone

The problem is when the player collides with the blackB the player doesn't stop. It slowly continues through the blackB. The IBAction is being used with a game loop. I need a way to freeze the player completely when it collides with the blackB. Any help is welcome, I am a beginner programmer. Thank you!
player and blackB are both UIImageViews
- (IBAction)right
{
direction = kright;
if (direction == kright)
{
rightMovement = CGPointMake(kMovement,0);
blockVelocity.x += rightMovement.x;
player.center = CGPointMake(player.center.x + blockVelocity.x,player.center.y);
if(CGRectIntersectsRect(player.frame, blackB.frame))
{
if(player.center.x < blackB.center.x)
{
if(blockVelocity.x > 0)
{blockVelocity.x = zero;
}
}
}
}
}

Sort of a sloppy answer, but in pseudo code:
-(IBAction)right {
if (playerCanMove==1) {
//move player
}
}
Set playerCanMove to 1 when the game loads, and set it to 0 on collision.

Related

Stop loop and start again from the beginning

I am trying to include enumerateChildNode with a For Loop. My code is below.
func movement() {
scene?.enumerateChildNodes(withName: "//enemy") {
(node, stop) in
enemyArray.append(node as! SKSpriteNode)
}
for i in enemyArray {
if enemy.position = player.position + 1 {
player.position = player.position + 1
}
continue
}
What the code above does is check for every enemy SKSpriteNode on the screen (lets say it finds 6), and then checks their positions relative to the player. If the players position is near the enemy position, it moves the players position, and then continues the for loop from where it was and checks the players position from the remaining enemies.
However, if the player moves near an enemy position that the for loop already checked (which was false at the time), it will miss that the player is near that enemy. EG: The for loop checks enemies 1,2,3 (finds 3 is near player and moves the player near 2) then checks 4,5,6. It will miss 2...
What I want the code to do
If enemy.position = player.position + 1 {
//move player
*stop the loop, and check the players position from the beginning of the for loop*
}
Call the method again and break out of the loop. But, this causes an infinite loop as you know while posting your question. Not sure how you're planning on changing the value of "i" since it's scope is within the method. Anyways here's how you achieve this:
var array = [1,2,3,4,5,6]
movement()
func movement() {
for i in array {
if i == 3 {
print("hi")
movement()
break
}
}
}

Player pauses for a second before moving (on some devices)

i have a 2d platformer with a player that moves. It works perfect in unity and i packaged it and downloaded the apk on my galaxy s7 which also works perfect.
I then tested it in my local supermarkets tablet display and on both tablets i tried, if i touched left, it would pause for a second, then move left.
The animated enemies, spinning coins and physics was working fine so there wasnt that type of lag, just a pause when moving which makes me think the code i have to move is wrong. The tablets looked fairly high spec too.
Here is how i move the player, i call this in the update function:
List<FingerTouch> currentTouches = new List<FingerTouch>();
public class FingerTouch
{
public int id;
public float beganXPos;
public FingerTouch (int fingerId, float fingerBegan)
{
this.id = fingerId;
this.beganXPos = fingerBegan;
}
}
if (!disableMovment)
{
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(i).phase == TouchPhase.Began && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
float xPos = Input.GetTouch(i).position.x;
if(xPos < Screen.width / 5)
{
playerLeft = true;
} else if (xPos > ((Screen.width / 5) * 4))
{
playerRight = true;
} else
{
playerUp = true;
}
int fingerId = Input.GetTouch(i).fingerId;
currentTouches.Add(new FingerTouch(fingerId, xPos));
} else if (Input.GetTouch(i).phase == TouchPhase.Ended)
{
if (currentTouches.Count != 0)
{
for (int j = 0; j < currentTouches.Count; j++)
{
FingerTouch currentTouch = currentTouches[j];
if (Input.GetTouch(i).fingerId == currentTouch.id || currentTouches.Count == 1)
{
if (currentTouches[j].beganXPos < Screen.width / 5)
{
playerLeft = false;
}
else if (currentTouches[j].beganXPos > ((Screen.width / 5) * 4))
{
playerRight = false;
}
else
{
playerUp = false;
}
currentTouches.RemoveAt(j);
break;
}
}
} else {
playerUp = false;
playerRight = false;
playerLeft = false;
}
}
}
}
It looks a little over the top but it basicily divides the screen into 3 sections 20/60/20 which move left right jump. When the user touches, it stores that touch and when its released, its removed.
This allows multi touch (jumping and moving) while also preventing jumping, sliding ur finger to the right and removing it and being in an unlimited jumping state as you didnt remove your finger in the middle.
Then after that it moves the player like this:
if (hitLeftWall && playerLeft)
{
playerBody.velocity = new Vector2(0, playerBody.velocity.y);
}
Is there anything here that would cause the player to pause before moving? Should this be in fixed update as the player has a rigidbody? Im new to unity so im not sure on the proper way to do things yet.

Make character only can jump when touching the ground

I want to make a character jump only when he is with his feet on the ground. I don't want him to be able to 'air-jump', so I came with this solution:
if (JumpButtonPressed()) {
if (GetComponent<BoxCollider2D>().IsTouchingLayers(LayerMask.NameToLayer("Ground"))) {
velocity.y = jumpForce;
}
}
The idea is that only when in touch with a "Ground" Layer, it can jump. But this is what happens:
It doesnt work just on his foot. If he is touching a platform by the side, it can jump as well. What could I do?
Use circle overlap with a position vector which is placed at the bottom on the player. Detect layer from there.
You may need to use different layer for platform if you want to write features like ledge grab, jump.
Create a bool isJumping and set it to true while in the air. When it reaches the ground - set it to false. Smth like that if your snippet is in Update():
bool isJumping = false;
if (JumpButtonPressed() && !isJumping) {
if (GetComponent<BoxCollider2D>().IsTouchingLayers(LayerMask.NameToLayer("Ground"))) {
velocity.y = jumpForce;
isJumping = true;
}
}
if (GetComponent<BoxCollider2D>().IsTouchingLayers(LayerMask.NameToLayer("Ground"))) {
isJumping = false;
}

Gun doesn't zoom out

I have a problem with my weapon's zoom script. I have been stuck on this for hours now. I have visited many sites in hope of solving my problem, but to no avail!
I don't think the problem has anything to do with Unity, but with my script instead. The code works perfectly fine when I zoom in (holding right click), but doesn't zoom out when I release right click and the animation has finished playing. It stays zoomed in! Once the animation has ended and I release right click, the weapon stays zoomed in.
The zoomIn() function works fine, but the gun doesn't zoom out during the zoomOut() function. I know the zoomOut() function works fine, because the camera's FOV resets back to what it was(60), but the animation doesn't rewind (maybe because it's stopped?). I have tried changing the animation's time, changing its speed and rewinding and many other things. If I am fully zoomed in and I zoom in again (I right click once the animation has finished playing), the gun jumps back to its original position and plays the zoom animation again.
The script makes perfect sense to me, so I don't know what is going on or how to fix it!
Below is my code:
#pragma strict
var arms : GameObject;
var zoomed : boolean = false;
function Update () {
if (Input.GetMouseButton(1) && zoomed == false) {
zoomIn();
}
if (!Input.GetMouseButton(1)) {
zoomOut();
}
}
function zoomIn() {
if (Input.GetMouseButton(1)) {
animation.Play("zoom");
camera.main.fieldOfView = 50;
arms.active = false;
yield WaitForSeconds(0.3);
zoomed = true;
}
}
function zoomOut() {
zoomed = false;
if (zoomed == false) {
animation.Rewind("zoom");
camera.main.fieldOfView = 60;
arms.active = true;
}
}
Please help
Thanks in advance
You're trying to use Animation.Rewind. This only rewinds the animation, but does not (AFAIK) play the animation in reverse
Try this out instead.
Replace your zoomIn() and zoomOut() methods with the below
function zoomIn() {
//A speed of 1 means that the animation will play at 1x in the positive timeline
animation["zoom"].speed = 1;
//Set the time to the FIRST key frame.
animation["zoom"].time = 0;
animation.Play("zoom");
camera.main.fieldOfView = 50;
arms.active = false;
yield WaitForSeconds(0.3);
zoomed = true;
}
function zoomOut() {
zoomed = false;
//A speed of -1 means that the animation will play the animation at 1x speed in reverse
animation["zoom"].speed = -1;
//Set the time to the LAST key frame. Replace the number "10" with the time of your last keyframe
animation["zoom"].time = 10;
animation.Play("zoom");
camera.main.fieldOfView = 60;
arms.active = true;
}

Starling stage touch.phase moving sprite to current location of touch on stage

I'm trying to move a sprite object (the hero) to the current location of the began touch event on the stage. Every time I touch on the stage it reads out the current globalX and globalY coordinates, but the sprite disappears from the stage so I don't know what I am doing wrong.
Here is my code:
private function onTouch(e:TouchEvent):void
{
var touch:Touch = e.getTouch(stage);
if(touch)
{
if(touch.phase == TouchPhase.BEGAN)
{
hero.x += touch.globalX;
hero.y += touch.globalY;
trace("Touched stage at position: " + touch)
}
else if(touch.phase == TouchPhase.ENDED)
{
//The Touch ended (MouseUp)
}
else if(touch.phase == TouchPhase.MOVED)
{
//dragging
}
}
}
Probably your hero sprite is added to Spirte with different size than the object you assigned the touch event. You need a sprite with for example screen size and the hero and the event added to it.
Hope that help :)