Snake Food Sprite - pygame

This is how food is drawn in my snake game. How would I apply the
"food" sprite to the food. The image is loaded on my computer and I
have gotten it to show up before but is never attached to the actual
food.
food = pygame.image.load('meat.png')
for (fx, fy) in self.food:
pygame.draw.rect(self.screen, FOOD_COLOR, (blockWidth * (fx-1), blockHeight * (fy-1), blockWidth, blockHeight))

The code is not drawing the food bitmap to the screen. Assuming there is a PyGame display named screen:
food_image = pygame.image.load('meat.png')
for (fx, fy) in self.food:
pygame.draw.rect(self.screen, FOOD_COLOR, (blockWidth * (fx-1), blockHeight * (fy-1), blockWidth, blockHeight))
screen.blit( food_image, ( fx, fy ) )

Related

Draw detection radius around square sprite [duplicate]

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Pygame collision with masks
(1 answer)
Closed 6 months ago.
I would like to draw sprites with 2 features: a base image (let's say a square image that I pass as argument) and a togglable view of their circular detection radius, for debug purposes and checking that collisions with a circular mask actually work.
Note: the main question is not about to detect collisions as in How do I detect collision in pygame?, but rather can a sprite have several surfaces attached to it and why is my draw_mask_outline function returning croppped circles? (see attached screenshots)
Here's an example of my class:
class Robot(pygame.sprite.Sprite):
def __init__(self, x, y, image, detection_radius, mouse_group, *groups):
super().__init__(*groups)
# extra image added for changing color if mouse is detected within
# detection radius
# I have used the mouse as a debug tool but in the end the Robot
# should have no knowledge of the other groups positions (and should
# not be able to compute a euclidean distance from a sprite group) but
# simply detect if a sprite of a certain sprite group has entered its
# radius
other_img = pygame.Surface((30, 30))
other_img.fill('black')
self.img_idx = 0
self.images = [image, other_img]
self.image = self.images[self.img_idx]
self.pos = pygame.Vector2(x, y)
self.rect = image.get_rect(center=self.pos)
self.detection_radius = detection_radius
self.mask_surface = pygame.Surface((detection_radius * 2, detection_radius * 2), pygame.SRCALPHA)
self.detection_mask = self.make_circle(self.notice_radius)
self.mask = pygame.mask.from_surface(
self.make_circle_surface(detection_radius))
sekf.mouse_group = mouse_group
def draw_mask_outline(self):
# this function should draw the outline of the circular detection mask
display_surf = pygame.display.get_surface()
pts = self.mask.outline()
for pt in pts:
x = pt[0] + self.rect.centerx
y = pt[1] + self.rect.centery
pygame.draw.circle(display_surf, 'black', (x, y), 1)
def make_circle_surface(self, radius):
# I used this function to generate the circular surface
mask_surf = pygame.Surface((radius * 2, radius * 2), pygame.SRCALPHA)
pygame.draw.circle(mask_surf, (0, 0, 0), (self.rect.centerx, self.rect.centery), radius)
return mask_surf
def collision(self):
# collision detection function, if mouse inside detection radius do something
if pygame.sprite.spritecollide(self, self.mouse_group, False, pygame.sprite.collide_mask):
pygame.draw.circle(pygame.display.get_surface(), (0, 0, 0), (self.rect.centerx, self.rect.centery), self.notice_radius, 1)
self.img_idx = 1
self.image = self.images[self.img_idx]
else:
self.img_idx = 0
self.image = self.images[self.img_idx]
def update(self):
# the overall update function where all the robot logic will happen
self.draw_mask_outline()
As fas as I've understood how the lib works, I should create a surface around the original image, big enough to fit the circle but this does not seem compatible with already having a self.image. Then I should draw a circle on that new surface.
Will this new surface follow the sprite when it moves too?
I managed to draw the circle inside the original image but this is not what is expected since the starting is smaller than the circle. In some cases, I also managed to generate surfaces, transform them to mask, then using the mask to generate an outline (hence the self.mask) but these outlines are always drawn far away from the sprite positions, are incomplete or completely missing...
Here are some screenshots of the current version and what I could achieve.
When the mouse is outside the detection ring, outlines are drawn with a severe offset, are sometimes incomplete and some robots have no outline.
Displaced and incomplete outlines
When the mouse is inside, the collision function draws the correct circle (but this is not the mask).
Collisions debug ring
Here are links to some solutions that I have tested and that did not work (if I've understood them correctly that is...):
pygame: mask non-image type surfaces
Pygame: Why i can't draw a circle sprite
how to create a circular sprite in pygame
OOP Pygame Circle
Ultimately the goal is to have the robots roam around and detect sprites from another group of robots that enter their detection radius.
Any help would be very much appreciated!

Detect image inside circle - HTML5 Canvas Game

I'm working on a HTML5 game using a canvas element.
I'm drawing a circle like this (the user can move this circle around):
ctx.arc(chomperX,chomperY,chomperRadius,0,Math.PI*2);
I'm placing bomb images on in the canvas like this:
ctx.drawImage(bombImg,bombX,bombY,15,15);
The objective is for the user to move the "chomper" circle over the bomb image and eat it. My questions is, how can I detect that the bomb is INSIDE the circle? I'm trying to do this by calculating the distance from the circle to the bomb image, but I'm getting mixed results. Here's how I'm getting the distance.
bx = bombX - chomperX;
by = bombY - chomperY;
bombDistance = Math.floor(Math.sqrt(bx * bx + by * by))
if (bombDistance < bombRadius + chomperRadius) { console.log("THE BOMB IS IN THE CIRCLE!"); }
Assuming the bombRadius is less than chomperRadius,
bx = bombX - chomperX;
by = bombY - chomperY;
bombDistance = Math.sqrt(bx * bx + by * by);
if (bombDistance < chomperRadius - bombRadius) { console.log("THE BOMB IS IN THE CIRCLE!"); }

libgdx calculate overlapping percentage?

I am using libgdx and I ned to calculate the overlapping percentage of 2 rects.
Actually it is the overlap of an Actor and a rectangle added to another Actor.
I want to highlight an actor if another actor is moved close to it so it is a proximity check.
And if there is 50% overlap I want to highlight. Then if the actor that is dragged close to the other is released with touch up i will let it slide close to the other actor.
So it is not simply collisioon detection, I need to know how much they collide.
You can easily achieve it using Libgdx Intersector class. You will need to create two Rectangles and third one for result - all you need to do is to check the areas after intersecting them
Actor a,b;
...
Rectangle r = new Rectangle(a.getX(), a.getY(), a.getWidth(), a.getHeight() );
Rectangle s = new Rectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight() );
Rectangle result = new Rectangle();
Intersector.intersectRectangles(r, s, result);
if( result.area() >= 0.5f * r.area() )
{
//do something if result area is equal to 50% a Actor area or more...
}

Sub coordinate system in Actor

is it possible to use a sub coordinate system in an actor?
I'd like to implement a simple flat progress bar, that draws an filled rect according to the current state of the progress bar.
My problem:
If i add a progress bar to a stage, that has for example a FitViewPort(10, 10) and the progress bar has a size of 10 width and 1 height, i've only the posibility to display 10 different states of the progress bar:
[-][-][-][-][-][-][-][-][-][-].
Can i use a different coordinate system in the progress bar,for example 100x10, so that i can display 100 different states? The size of the progress bar should be defined in the stage's coordinate system 10x10.
Thanks
Mario
the best solution will be to keep actor's (x, y) in some variabes and then calculate position on stage using localToStageCoordinates. Then you can also scale local coordinates. The following code is an example how to achieve it:
Actor a = new Actor();
//...
float actorX = 0, actorY = 86;
float xScl = 1, yScl = 0.1f;
//... //modify inside-actor coordinates
Vector2 positionOnStage = a.localToStageCoordinates( new Vector2(actorX * xScl, actorY * yScl )); //calculate stage coordinates fom local actor's

rotation problems when firing

I have a big problem when I try to rotate my projectiles along with the ship's rotation.
I want my spaceship shoot two shots at once. So I used my first array of projectiles and placed them at the right side of the ship (one shot on the left and one on the right). So far so good.
But when I shoot with my spaceship and I turn around the rotations of the projectiles look very strange. It's hard to describe so here's an image that shows the error in action.
http://imageshack.us/photo/my-images/841/projectilebug.jpg
I have huge problems rotating the projectiles ALONG with the spaceship so that it looks really good. Currently there is one single shot only. My shooting gets screwed up when I rotate and fire at once.
The goal is to create a dual firing cannon like in the picture shown.
Here is some code that places the projectile at the left of the ship (that doesn't really work):
var projectileRadians:Number = (player.frame / 180) * 3.14159;
tempProjectile.x = (player.point.x + 6) + Math.cos(projectileRadians);
tempProjectile.y = (player.point.y + 3) + Math.sin(projectileRadians);
The velocity code:
tempProjectile.nextX = tempProjectile.x;
tempProjectile.nextY = tempProjectile.y;
tempProjectile.dx = rotationVectorList[player.frame].x;
tempProjectile.dy = rotationVectorList[player.frame].y;
This updates the position:
nextX += (dx * (speed + Math.abs(xAdjust))) * step;
nextY += (dy * (speed + Math.abs(yAdjust))) * step;
The velocity code looks ok. You don't seem to be calculating the gun position correctly.
Edit: we're not using the standard trig frame of reference; instead, we're using one where angle=0 means up and angles increase as you rotate clockwise. So we take the standard usage and swap sin and cos.
Here, gx and gy mean the coordinates of a gun relative to the coordinates around which the ship moves. We need to rotate the vector <gx, gy> by the angle before adding it to the ship coords:
cs = Math.cos(projectileRadians);
sn = Math.sin(projectileRadians);
tempProjectile.x = player.point.x + gx * sn - gy * cs;
tempProjectile.y = player.point.y + gx * cs + gy * sn;
It would be a good optimization to restrict the ship's angle to certain values (perhaps every 5 degrees), and put all the trig functions into a table ahead of time. Trig functions are expensive to compute.
Note that this also assumes that positive Y is "up". Computer graphics often start with (0, 0) in the upper left corner and increase Y as you move down, so you may have to switch the sign of Y.