I'm trying to make my bullet look at my cursor [duplicate] - pygame

This question already has answers here:
How do you point the barrel towards mouse in pygame?
(1 answer)
calculating direction of the player to shoot pygame
(1 answer)
How to move a sprite according to an angle in Pygame
(3 answers)
Closed 7 months ago.
I've got my player in the center of my screen and I want a bullet at a fixed distance from the player pointing at my cursor. I've got the fixed distance down and the angle in degrees, but the bullet spins around violently when I move my cursor. What am I doing wrong?
radius = 100
mouse = pg.mouse.get_pos()
delta_x = mouse[0] - (Width/2)
delta_y = -(mouse[1] - (Height/2))
Rotation = math.degrees(math.atan2(delta_y, delta_x))
if Rotation > 0:
angle = (360 - Rotation)
elif Rotation < 0:
angle = -(Rotation)
x, y = (radius*(math.sin(angle))), (radius*(math.cos(angle)))
Bullet_x = (Width/2 + x)
Bullet_y = (Height/2 + y)
screen.blit(Bullet, (Bullet_x, Bullet_y))

Related

Pygame need to build sprite from a rotating and non rotating image [duplicate]

This question already has answers here:
How to set the pivot point (center of rotation) for pygame.transform.rotate()?
(5 answers)
How can you rotate an image around an off center pivot in Pygame
(1 answer)
How do I rotate an image around its center using Pygame?
(6 answers)
Closed 22 days ago.
I have an interesting problem with sprits in pygame.
Essentially, I am trying to create an archer sprite which will follow a target.
To do so, I need it to rotate. Naturally, I don't want the whole archer to rotate - just his shoulders/head etc. To do so I have create two separate spritesheets (for the top and bottom)
I can then create the sprite image using:
class Archer(pygame.sprite.Sprite):
def __init__(self, group, pos, size):
super().__init__(group)
self.pos = pos
self.assets_legs = GetAssets('../graphics/archer_fixed.png', size)
self.frames_legs = self.assets_legs.sprite_images
self.assets_body = GetAssets('../graphics/archer_rotate.png', size)
self.frames_body = self.assets_body.sprite_images
self.frame_index = 0
self.angle = 0
self.archer = [self.frames_legs[round(self.frame_index)], self.frames_body[round(self.frame_index)]]
self.image = pygame.Surface((size), pygame.SRCALPHA)
for image in self.archer:
self.image.blit(image, (0,0))
This is fine and works well. However, when I want to rotate the top half and blit this to the self.image, as in:
def rotate(self):
self.rot_img = self.archer[1]
self.rot_img = pygame.transform.rotate(self.rot_img, 1)
self.image = pygame.Surface((75,75), pygame.SRCALPHA)
self.archer = [self.frames_legs[round(self.frame_index)], self.rot_img]
for image in self.archer:
self.image.blit(image, (0,0))
self.rect = self.image.get_rect(center = self.pos)
I get strange artifacts. I suspect because I am trying to blit a surface with a rotated dimension to a self.image. The only work around I can think of is to create two separate sprites and then have them track each other, but the must be a way to do this in one class.
Any ideas?
Cheers

make enemy ricochet off walls pygame [duplicate]

This question already has answers here:
How do I make my monster move randomly in my game
(1 answer)
How do I randomly move objects in a maze using pygame? [closed]
(1 answer)
Closed 24 days ago.
This post was edited and submitted for review 23 days ago and failed to reopen the post:
Original close reason(s) were not resolved
Note: This is different to my previous question. The previous question I posted was about the enemy following the player, but here I want the zombie to roam around. My plan is to link these together (once they both work correctly) and have the zombie roam around until the player is within a certain radius. I would appreciate if this can be reopened as this is a different problem!
So i am trying to create an enemy that moves around the map and 'bounces' off any walls it collides with. I have tried to adapt some code i used making pong a while ago. I tried to break the problem down and consider where the enemy is hitting the wall from, but i feel like i may be overcomplicating it? Here is a video of the bug: https://imgur.com/a/H2qOMZD
This is my current code.
class Enemy(pygame.sprite.Sprite):
def __init__(self, position):
super().__init__(enemy_group, all_sprites_group)
self.position = pygame.math.Vector2(position)
self.wander_speed = pygame.math.Vector2((6 * random.choice((-1,1))), (6 * random.choice((-1,1))))
def walk_around(self):
self.velocity = self.wander_speed
print(self.velocity)
self.position += self.velocity
self.base_zombie_rect.centerx = self.position.x
self.base_zombie_rect.centery = self.position.y
self.base_zombie_rect.centerx, self.base_zombie_rect.centery = self.position.x, self.position.y
self.check_collision_2()
self.rect.center = self.base_zombie_rect.center
self.position = (self.base_zombie_rect.centerx, self.base_zombie_rect.centery)
def check_collision_2(self):
for sprite in obstacles_group:
if sprite.rect.colliderect(self.base_zombie_rect):
if self.base_zombie_rect.top < sprite.rect.bottom and self.base_zombie_rect.centery > sprite.rect.bottom: # UP collision
print("UP COLLISION")
self.velocity.y *= -1
if self.base_zombie_rect.bottom > sprite.rect.top and self.base_zombie_rect.centery < sprite.rect.top: # DOWN collision
print("DOWN COLLISION")
self.velocity.y *= -1
if self.base_zombie_rect.left < sprite.rect.right and self.base_zombie_rect.centerx > sprite.rect.right: # LEFT collision
print("RIGHT COLLISION")
self.velocity.x *= -1
if self.base_zombie_rect.right > sprite.rect.left and self.base_zombie_rect.centerx < sprite.rect.left: # RIGHT collision
print("LEFT COLLISION")
self.velocity.x *= -1

How can I make my sprite move accross the screen? [duplicate]

This question already has answers here:
How to make a circle move diagonally from corner to corner in pygame
(1 answer)
How to make smooth movement in pygame
(2 answers)
Closed 2 years ago.
When a certain value is met I want my enemy sprite to return to his intial position,but now hes just disappearing and reappearing in that position.
I'm only changing the Y position
def update(self):
self.count += 1
x_component = self.ship.rect.centerx-self.enemy2X
y_component = self.ship.rect.centery-self.enemy2Y
distance = math.hypot(x_component, y_component)
if distance < 200:
self.currentState = 1
print distance
elif distance > 200:
self.currentState = 0
self.enemy2Y=68
print self.enemy2Y

circularly layout smaller squares within a large square

Given a bounding square and the total number of smaller squares. The smaller squares need to be drawn within the bigger square evenly spaced out in a circular fashion, just touching but not overlapping. How do you compute the width of the inner square ?
(updated fiddle link)
http://jsfiddle.net/mdluffy/6bUVz/3/
///////// INPUTS ///////////////////////////////////////////
var BoundingBoxSide = 100;
var NofInnerBoxes = 14;
////////////////////////////////////////////////////////////
drawBoxes();
function drawBoxes()
{
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rect(0,0,BoundingBoxSide,BoundingBoxSide);
ctx.stroke();
for(var i=0; i < NofInnerBoxes; i++)
{
// ************************************************************************************ //
// This needs to be computed so that the boxes touch each other, but not overlap
var innerBoxSide = 20;
// ************************************************************************************ //
var angle = degToRad(i * 360/NofInnerBoxes);
var innerX = ((BoundingBoxSide - innerBoxSide)/2) * Math.cos(angle);
var innerY = ((BoundingBoxSide - innerBoxSide)/2) * Math.sin(angle);
ctx.rect(BoundingBoxSide/2 + innerX - innerBoxSide/2, BoundingBoxSide/2 - innerY - innerBoxSide/2, innerBoxSide, innerBoxSide);
ctx.stroke();
}
}
function degToRad(d)
{
return d * Math.PI / 180;
}
Update:
I'm working on a 3D visualization using Three.js. This is a tree structure with nodes represented as cubes. The child node cubes are layed out circularly on top of the parent node cubes. Applied recursively.
The inner squares need not touch the outer squares, but it should touch the largest circle that can be fit inside the outer square.
Here's my attempt:
var alpha = Math.PI * (NofInnerBoxes - 2) / (2 * NofInnerBoxes)
var t = Math.tan(alpha)
var innerBoxSide = BoundingBoxSide / Math.sqrt(t*t + 4*t + 5)
(Credit: to WolframAlpha for solving for innerBoxSide; and to an envelope I doodled on the back of.)
Update: The above was under the assumption that two sides of each inner square are parallel to a line that passes through the centers of that inner square and the outer square. I now see that this assumption was not what you had in mind.
Here's another approach. In this one, the circles that circumscribe the inner squares will all touch each other, though the inner squares themselves will not quite touch each other:
var alpha = Math.PI / NofInnerBoxes
var t = Math.sin(alpha)
var innerBoxSide = BoundingBoxSide * t / ((t + 1) * Math.sqrt(2))
Result:
Derivation
In response to the request for how the formula was derived...
Let r_s (r sub s) be the "small radius", i.e. the radius of the circles that circumscribe the inner squares. These inner circles are all tangent to the big circle that inscribes the outer square. Call the radius of the big circle r_b (b for "big").
Note that the side of the outer square, a.k.a. BoundingBoxSide, is = 2 * r_b. Note also that the diameter of each inner circle, 2 * r_s, is also the diagonal of each inner square. Therefore the side of each inner square, a.k.a. innerBoxSide, is = (2 * r_s) / sqrt(2).
Now let angle alpha = half the angle that each inner circle subtends (if that's the right verb) around the center of the big circle. I.e. alpha = (2 * pi / NofInnerBoxes) / 2 = pi / NofInnerBoxes.
The key is to draw a right triangle, where one of the angles is alpha; this will tell us the ratios between all the sides of that triangle, using trig functions like sin(). And we can draw such a triangle whose vertices are:
A. The center of the big circle
B. The center of a small circle
C. The point where that small circle touches its neighbor
The right angle is at vertex C, and the angle alpha is at vertex A. The length of side BC = r_s, and the length of the hypotenuse (AB) = r_b - r_s.
So by the definition of sin(), we can say that sin(alpha) = opposite side / hypotenuse = BC / AB = r_s / (r_b - r_s). Solve this equation for r_s, and we get r_s = r_b * sin(alpha) / (1 + sin(alpha)).
Finally, plug in the fact (above) that BoundingBoxSide = 2 * r_b, and innerBoxSide = (2 * r_s) / sqrt(2); and you get the formula shown above, innerBoxSide = BoundingBoxSide * t / ((t + 1) * Math.sqrt(2)).
Sorry this is a longish wall of text, but I hope it's sufficiently clear if read carefully. I may post a diagram as well, if time allows. Let me know if you have questions. (There's probably an easier way to derive this, but that's how I did it.)

How to make my character move relative to the mouse position with actionscript 3?

ok so i have a character called character_mc and i want it to move towards the mouse when you press the forward arrow and strafe relative to right angles of that.
i am quite new to actionscript so could you please include and example of your code in my original code
Here is my current code:
import flash.events.MouseEvent;
//Event Listners
stage.addChild(crosshair_mc);
crosshair_mc.mouseEnabled = false;
crosshair_mc.addEventListener(Event.ENTER_FRAME, fl_CustomMouseCursor);
function fl_CustomMouseCursor(event:Event)
{
crosshair_mc.x = stage.mouseX;
crosshair_mc.y = stage.mouseY;
}
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,facecursor);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_KeyboardDownHandler);
//Functions
function facecursor(event):void
{
character_mc.rotation = (180 * Math.atan2(mouseY - character_mc.y,mouseX - character_mc.x))/Math.PI + 90;
}
function fl_KeyboardDownHandler(event:KeyboardEvent):void
{
trace("Key Code Pressed: " + event.keyCode);
if (event.keyCode == 38)
{
character_mc.y = character_mc.y - 5;
}
if (event.keyCode == 40)
{
character_mc.y = character_mc.y + 5;
}
if (event.keyCode == 39)
{
character_mc.x = character_mc.x + 5;
}
if (event.keyCode == 37)
{
character_mc.x = character_mc.x - 5;
}
}
I can tell you the basic concept of how you could do this, but you'll have to apply it to your own code. To involves converting your movement code to use a vector, then modifying the vector to get a direction facing the mouse (or at right angles to that direction) and a little bit of math.
Right now you have the character moving straight along the x and y axis only in each key press case. Left/Right only move along the X and Up/Down only move along the Y.
To move towards the mouse will require the character to move both along the X and Y when the Up/Down/Left/Right keys are pressed. Clearly you can see if you move both the character's x/y positions by the same amount, say 5, then it'll move exactly at 45 degrees (though it'll actually move a step of 7.07 pixels, hopefully you can see why). You can represent this as a vector: (5,5). You can use a Point object to represent this vector:
var movementVector:Point = new Point(5, 5);
trace(movementVector.x); // gives 5
trace(movementVector.y); // also gives 5
With that in mind, you can also use a vector to represent movement straight up and down on the y axis:
// set the x to 0 and y to 5
movementVector.x = 0; // 0 would mean not to move the character along the x
movementVector.y = 5; // using -5 would move the character up
And to move along the x axis only:
movementVector.x = 5; // using -5 would move the character right
movementVector.y = 0; // 0 would mean not to move the character along the y
To do the actual movement of the character would be the same as you are doing now, except you use the vector's values:
character_mc.x = character_mc.x + movementVector.x;
character_mc.y = character_mc.y + movementVector.y;
Now to figure out the proper vector to move on a diagonal from the character's position to the mouse position is pretty simple. The x value of the vector is the x distance from the character to the mouse, and the y value of the vector is the y distance from the character to the mouse.
Let's say the character is ay 125, 100 and the mouse at 225, 150. This means the distance between the character and mouse is 100, 50 x and y. Thus you'd end up with a vector:
movementVector.x = 100;
movementVector.y = 50;
If you were to apply this vector as it is to the character's position as it is, it would arrive at the mouse instantly (and then go beyond it) as the character is moving 100 pixels along the x and 50 pixels along the y right away. The step size would be 111.8 pixels long -too big. You would need to scale it down to the character's speed. You can do this by calling the normalise() method on the Point class to scale down the vector:
trace(movementVector.x); // gives 100
trace(movementVector.y); // gives 50
// assuming '5' is the max speed of the character
movementVector.normalise(5);
trace(movementVector.x); // gives 4.47213595499958
trace(movementVector.y); // gives 2.23606797749979
This would result in a 'step' size of 5 now. Applying this would make your character move 5 pixels towards a point 100 pixels to the right and 50 pixels down from where it started.
To transform a vector exactly 90 degrees, a quick and simple way is to swap the x and y values around.
If you are curious on what normalise() method mathematically does, is that it takes the x and y values of the vector (or point) and divides it by the length to get a unit vector (or a vector with a step size of 1), then times the input you give it to scale it to the desired length.
To move your character_mc towards the mouse point you only need the direction vector between the two:
var dir:Point = new Point(mouseX - character_mc.x, mouseY - character_mc.y);
dir.Normalize();
// The following should be called when the 'up' or 'forward' arrow is pressed
// to move the character closer to mouse point
character_mc.x += dir.x; // dir can be multiplied by a 'speed' variable
character_mc.y += dir.y;
Strafing left and right around the point is a little more tricky:
// Where radius is the distance between the character and the mouse
character_mc.x = mouseX + radius * Math.cos(rad);
character_mc.y = mouseY + radius * Math.sin(rad);
You should find this tutorial useful as it does everything you describe and more:
http://active.tutsplus.com/tutorials/actionscript/circular-motion-in-as3-make-one-moving-object-orbit-another/