Godot: 2D Raycast is going opposite directions - 2d

Just started learning Godot and am having trouble with 2D Raycasts going left instead of right or right instead of left.
So I've got a basic top down 2D game with a raycast on the player. Facing up and down works perfectly fine, it's just left and right that are causing headaches. The code looks fine, so that's why I'm here
onready var rayCast = get_node("RayCast2D")
func _physics_process(delta):
vel = Vector2()
# inputs
if Input.is_action_pressed("move_up"):
vel.y -= 1
facingDir = Vector2(0, -1)
if Input.is_action_pressed("move_down"):
vel.y += 1
facingDir = Vector2(0, 1)
if Input.is_action_pressed("move_left"):
vel.x -= 1
facingDir = Vector2(1, 0)
if Input.is_action_pressed("move_right"):
vel.x += 1
facingDir = Vector2(-1, 0)
vel = vel.normalized()
move_and_slide(vel * moveSpeed)
manage_animations()
func manage_animations ():
if vel.x > 0:
play_animation("MoveRight")
elif vel.x < 0:
play_animation("MoveLeft")
elif vel.y < 0:
play_animation("MoveUp")
elif vel.y > 0:
play_animation("MoveDown")
elif facingDir.x == -1:
play_animation("IdleRight")
elif facingDir.x == 1:
play_animation("IdleLeft")
elif facingDir.y == -1:
play_animation("IdleUp")
elif facingDir.y == 1:
play_animation("IdleDown")
func _process(delta):
if Input.is_action_just_pressed("interract"):
try_interact()
func try_interact():
rayCast.cast_to = facingDir * interactDist
if rayCast.is_colliding():
if rayCast.get_collider() is KinematicBody2D:
rayCast.get_collider().take_damage(damage)
elif rayCast.get_collider().has_method("on_interact"):
rayCast.get_collider().on_interact(self)
I've tried changing the Vector2 x and y variables in the move left and right and while that works, the walking is all messed up then.
Any ideas?

Related

Why isn't my code working for basic Movement in Godot?

I just started a new project in godot. So far I have one png which is the main player. I have added a sprite and CollisionShape2D to the player. When i run the game the player does not move (using keys). Does anyone know what is going on here? Heres my code:
extends KinematicBody2D
export var speed = 10.0
export var tileSize = 32.0
var initpos = Vector2()
var dir = Vector2()
var facing = 'down'
var counter = 0.0
var moving = false
func _ready():
initpos = position
func _process(delta):
if not moving:
set_dir()
elif dir != Vector2():
move(delta)
else:
moving = false
func set_dir(): #set moving
dir = get_dir()
if dir.x != 0 or dir.y != 0:
moving = true
initpos = position
func get_dir(): #user input
var x = 0
var y = 0
if dir.y == 0:
x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
if dir.x == 0:
y = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
return Vector2(x, y)
func move(delta): #move player linearly
counter += delta + speed
if counter >= 1.0:
position = initpos + dir * tileSize
counter = 0.0
moving = false
else:
position = initpos + dir * tileSize * counter
EDIT:
I have also tried copying and pasting the code directly from Godots documentation and the player still does not move:
extends KinematicBody2D
export (int) var speed = 200
var velocity = Vector2()
func get_input():
velocity = Vector2()
if Input.is_action_pressed('right'):
velocity.x += 1
if Input.is_action_pressed('left'):
velocity.x -= 1
if Input.is_action_pressed('down'):
velocity.y += 1
if Input.is_action_pressed('up'):
velocity.y -= 1
velocity = velocity.normalized() * speed
func _physics_process(delta):
get_input()
velocity = move_and_slide(velocity)
I figured it out. When adding a new script I did not add it to the Player but to the scene.

Collision detection is not working correctly

I have to submit a Breakout clone and I'm struggling with the collision detection of the ball and the bricks. Basically, the collision detection works, but the ball destroys the brick about 10 pixels away from the visual object. I'm checking the bounds of both objects, but I guess the problem is that the ball is a moving object and the brick is a static one.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
brick = brickArray[i][j];
if (brick == null)
continue;
areBricksLeft = true;
Bounds brickBounds = brick.getBoundsInParent();
Bounds ballBounds = ball.getBoundsInParent();
if (brickBounds.intersects(ballBounds) ) {
brick.removeBrickAt(i, j, brick, brickArray, brickPane);
didHitBrick = true;
}
}
}
Thanks for the hint I found the mistake. I replaced my condition with this:
double ballX = ball.getLayoutX() + ball.getRadius();
double ballY = ball.getLayoutY() + ball.getRadius();
if ((ballX <= brickBounds.getMaxX() - 10 && ballX >= brickBounds.getMinX() -10) &&
(ballY <= brickBounds.getMaxY() - 10 && ballY >= brickBounds.getMinY() - 10)) {
brick.removeBrickAt(i, j, brick, brickArray, brickPane);
didHitBrick = true;
}
Now it is possible to adjust the collision by substracting and adding values to the bounds.

Pygame,shooting bullets using vectors

Ok so all night me and 5 other guys have been working on a project for our pygame module.Our lecturer hasn't given us any programs to reference from he has just throw a bunch of code at us (without commenting) and expecting us to understand it.We only started python since the start of september.We really need some help.
So we have one human player which is controlled by W A S & D and 15 random dots moving around the screen.We need to use vectors(which we have never used) to shoot at the random dots.
Please someone help.
edit code added~
import pygame
class Terminator(pygame.sprite.Sprite):
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((20, 20))
self.image.fill((0, 0, 0))
pygame.draw.circle(self.image, (255, 0, 0), (10, 10), 10, 0)
self.rect = self.image.get_rect()
self.dx = screen.get_width()/2
self.dy = screen.get_height()/2
self.rect.center = (self.dx, self.dy)
self.speed = 5
self.screen = screen
def update(self):
self.rect.center = (self.dx, self.dy)
def MoveLeft(self):
if self.rect.left < 0:
self.dx += 0
else:
self.dx -= self.speed
def MoveRight(self):
if self.rect.right > self.screen.get_width():
self.dx += 0
else:
self.dx += self.speed
def MoveUp(self):
if self.rect.top <0:
self.dy += 0
else:
self.dy -= self.speed
def MoveDown(self):
if self.rect.bottom > self.screen.get_height():
self.dy += 0
else:
self.dy += self.speed
<code>
humansprite.py
<pre>
import pygame
import random
import math
class Humans(pygame.sprite.Sprite):
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((16, 16))
self.image.fill((0, 0, 0))
pygame.draw.circle(self.image, (0, 0, 255), (8, 8), 8, 0)
self.rect = self.image.get_rect()
self.dx = random.randrange(0, screen.get_height())
self.dy = random.randrange(0, screen.get_width())
self.screen = screen
self.speed = 1
self.alive = True
def update(self):
self.rect.centerx -= self.dx
self.rect.centery -= self.dy
if self.rect.right < 0:
self.reset()
def reset(self):
self.rect.left = self.screen.get_width()
self.rect.centery = random.randrange(0, self.screen.get_height())
self.dy = random.randrange(-2, 2)
self.dx = random.randrange(1, 4)
<code>
seekandDestory.py
<pre>
import pygame
from TerminatorSprite import Terminator
from humansSprite import Humans
pygame.init()
def checkKeys(myData):
(event, ship) = myData
if event.key == pygame.K_LEFT:
print 'LEFT'
ship.MoveLeft()
if event.key == pygame.K_RIGHT:
print 'RIGHT'
ship.MoveRight()
if event.key == pygame.K_UP:
print 'UP'
ship.MoveUp()
if event.key == pygame.K_DOWN:
print 'DOWN'
ship.MoveDown()
def main():
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Seek and Destroy")
background = pygame.Surface(screen.get_size())
clock = pygame.time.Clock()
screen.blit(background, (0, 0))
terminator = Terminator(screen)
humans = []
for people in range(15):
people = Humans(screen)
humans.append(people)
terminatorGroup = pygame.sprite.Group(terminator)
humanGroup = pygame.sprite.Group(humans)
clock = pygame.time.Clock()
keepGoing = True
pygame.key.set_repeat(10, 10)
while keepGoing:
clock.tick(60)
pygame.mouse.set_visible(False)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
if event.type == pygame.KEYDOWN:
myData = (event, terminator)
checkKeys(myData)
#if pygame.sprite.spritecollide(terminator, humanGroup, False):
terminatorGroup.clear(screen, background)
terminatorGroup.update()
terminatorGroup.draw(screen)
humanGroup.clear(screen, background)
humanGroup.update()
humanGroup.draw(screen)
pygame.display.flip()
pygame.mouse.set_visible(True)
if __name__ == "__main__":
main()
<code>
I just finished up this set of examples last night! Check out the Lunar Lander example, especially the way I'm handling vectors in lunarlander.py - it provides a class, V, for vector management.
What you'll probably need is a sprite for your guy with a vector representing his speed (moment-to-moment, probably 0) and angle, then a sprite for each random dot with a similar vector and angle. When you shoot, create a new sprite with a vector whose angle matches the current angle your guy is facing and magnitude matches the speed of the bullet. Then, in the update() method, move each sprite (bullet, random-dot). Very similar to what I'm doing in lunarlander.py.
Good luck! If you've just started Python, that's a tough assignment. Happy coding!

Determine position of number in a grid of numbers centered around 0 and increasing in spiral

I've got the following grid of numbers centered around 0 and increasing in spiral. I need an algorithm which would receive number in spiral and return x; y - numbers of moves how to get to that number from 0. For example for number 9 it would return -2; -1. For 4 it would be 1; 1.
25|26|... etc.
24| 9|10|11|12
23| 8| 1| 2|13
22| 7| 0| 3|14
21| 6| 5| 4|15
20|19|18|17|16
This spiral can be slightly changed if it would help the algorithm to be better.
Use whatever language you like. I would really appreciate mathematical explanation.
Thank you.
First we need to determine which cycle (distance from center) and sector (north, east, south or west) we are in. Then we can determine the exact position of the number.
The first numbers in each cycle is as follows: 1, 9, 25
This is a quadratic sequence: first(n) = (2n-1)^2 = 4n^2 - 4n + 1
The inverse of this is the cycle-number: cycle(i) = floor((sqrt(i) + 1) / 2)
The length of a cycle is: length(n) = first(n+1) - first(n) = 8n
The sector will then be:
sector(i) = floor(4 * (i - first(cycle(i))) / length(cycle(i)))
Finally, to get the position, we need to extrapolate from the position of the first number in the cycle and sector.
To put it all together:
def first(cycle):
x = 2 * cycle - 1
return x * x
def cycle(index):
return (isqrt(index) + 1)//2
def length(cycle):
return 8 * cycle
def sector(index):
c = cycle(index)
offset = index - first(c)
n = length(c)
return 4 * offset / n
def position(index):
c = cycle(index)
s = sector(index)
offset = index - first(c) - s * length(c) // 4
if s == 0: #north
return -c, -c + offset + 1
if s == 1: #east
return -c + offset + 1, c
if s == 2: #south
return c, c - offset - 1
# else, west
return c - offset - 1, -c
def isqrt(x):
"""Calculates the integer square root of a number"""
if x < 0:
raise ValueError('square root not defined for negative numbers')
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = 2**(a+b)
while True:
y = (x + n//x)//2
if y >= x:
return x
x = y
Example:
>>> position(9)
(-2, -1)
>>> position(4)
(1, 1)
>>> position(123456)
(-176, 80)
Do you mean something like this? I did not implement any algorithm and the code can be written better but it works - that's always a start :) Just change the threshold value for whatever you wish and you'll get the result.
static int threshold=14, x=0, y=0;
public static void main(String[] args) {
int yChange=1, xChange=1, count=0;
while( !end(count) ){
for (int i = 0; i < yChange; i++) {
if( end(count) )return;
count++;
y--;
}
yChange++;
for (int i = 0; i < xChange; i++) {
if( end(count) )return;
count++;
x++;
}
xChange++;
for (int i = 0; i < yChange; i++) {
if( end(count) )return;
count++;
y++;
}
yChange++;
for (int i = 0; i < xChange; i++) {
if( end(count) )return;
count++;
x--;
}
xChange++;
}
}
public static boolean end(int count){
if(count<threshold){
return false;
}else{
System.out.println("count: "+count+", x: "+x+", y: "+y);
return true;
}
}

box2d difference between angles of two bodies

Working with box2d and cocos2d, I've calculated two vectors:
one is the vector pointing in the direction the car is travelling. (center of the vehicle to it's north point).
two is the vector pointing in the direction of the target. (center to the vehicle to the target center.)
I need to rotate the vehicle to also point in the direction of the target. This is done by setting the vehicle's steering either 90 degrees to turn right or -90 to turn left.
At the moment i'm querying the box2d body of the vehicle for its angle, then calculating the angle of the target direction vector using:
if(vector.y == 0){ vector.y = 0.000001f; }
float baseRadians = atan(vector.x/vector.y);
if(vector.y < 0){ baseRadians += PI_CONSTANT; } //Adjust for -Y
return -1 * baseRadians;
The following is crude and where I need help...!
I then compare the angle of the vehicle against the angle returned from the direction vector and set the steering as follows:
if(vehicleAngle < targetAngle)
{
steeringInput = -90.0;
}
else if(vehicleAngle > targetAngle)
{
steeringInput = 90.0;
}
else
{
steeringInput = 0.0;
}
The problem is two fold:
The target angle jumps from -4.71 to 1.57 radians, causing the vehicle to switch to the wrong direction
The vehicle angle is continous and keeps increasing rather than staying within a range.
Is there a way to get both the target vector and the vehicle angle in a set range where, for example, if the target angle is 0-360 and the van angle is 0-360, i can then compare them accurately?
Any other way to do this...? Any help appreciated!
Use atan2 instead of atan in your code. It gets the angle from one object to another.
Using the atan2f function instead I managed to get the vehicle vector angle and target vector angle.
my new implementation is as follows:
//get the direction the vehicle is facing and the direction the target is facing
CGPoint vehicleDirectionVector = ccpNormalize(ccpSub(ccp(vehicleBonnetTip.x*PTM_RATIO, vehicleBonnetTip.y*PTM_RATIO), ccp(vehicleCenter.x*PTM_RATIO, vehicleCenter.y*PTM_RATIO)));
CGPoint targetDirectionVector = ccpNormalize(ccpSub(ccp(origTarget.x, origTarget.y), ccp(vehicleCenter.x*PTM_RATIO, vehicleCenter.y*PTM_RATIO)));
vehicleAngle = atan2f(vehicleDirectionVector.x,vehicleDirectionVector.y);
targetAngle = atan2f(targetDirectionVector.x,targetDirectionVector.y);
if ( targetAngle < -M_PI / 2 && vehicleAngle > M_PI / 2 ) targetAngle += M_PI * 2;
if ( targetAngle > M_PI / 2 && vehicleAngle < -M_PI / 2 ) targetAngle -= M_PI * 2;
if ( vehicleAngle < -M_PI / 2 && targetAngle > M_PI / 2 ) vehicleAngle += M_PI * 2;
if ( vehicleAngle > M_PI / 2 && targetAngle < -M_PI / 2 ) vehicleAngle -= M_PI * 2;
CCLOG(#"vehicle angle is %f, target angle is %f", vehicleAngle, targetAngle);
Then to set my steering, crudely (i'm still working on this one..) i do:
if(vehicleAngle < targetAngle)
{
steeringDegrees = 90.0;
}
else if(vehicleAngle > targetAngle)
{
steeringDegrees = -90.0;
}
else
{
steeringDegrees = 0.0;
}

Resources