moving an object in a circular path [duplicate] - python

This question already has answers here:
Why it doesn't spin in a circle? And how to fix it?
(1 answer)
Ship moves up and left faster than down and right when rotating in pygame
(1 answer)
Closed 2 years ago.
This question is related to
My code is below. You can use any small image for my images.
import sys, os, pygame, itertools
from math import sin,cos,pi, radians
from pygame.locals import *
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50,50) #Set window position
pygame.init()
clock = pygame.time.Clock()
FPS = 1000
SCREENW = 800 #screen width
SCREENH = 740 #screen height
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
ORANGE = (128, 100, 30)
FONT1= "Cookie-Regular.ttf"
SCREEN = pygame.display.set_mode((SCREENW, SCREENH), 0, 32) #display screen
clock = pygame.time.Clock()
#-------------------------------------------------------------------------------
def maketext(msg,fontsize, colour = ORANGE, font = FONT1):
mafont = pygame.font.Font(font, fontsize)
matext = mafont.render(msg, True, colour)
matext = matext.convert_alpha()
return matext
#-------------------------------------------------------------------------------
def print_info():
""""""
textcos = maketext(str(round(obj.rect.x, 2)) + " " + str(round(obj.rect.y, 2)), 30)
SCREEN.blit(textcos, (obj.rect.x, obj.rect.y + 30))
#-------------------------------------------------------------------------------
class object_factory(pygame.sprite.Sprite):
def __init__(self, imagelist, xpos, ypos, speedx = 0, speedy = 0, value = 0):
"""Constructor"""
pygame.sprite.Sprite.__init__(self)
self.name = ""
self.frame = 0
self.imagelist = imagelist
self.image = imagelist[self.frame]
self.mask = pygame.mask.from_surface(self.image) # pixelmask
self.rect = self.image.get_rect()
self.rect.x = xpos
self.rect.y = ypos
#self.speedx = speedx
#self.speedy = speedy
self.timer = 0
self.timerlimit = 10
#----------------------------------------------------------------------
#def move(self): # wallsprites, Herosprite, looptime
#self.rect.x += self.speedx
#self.rect.y += self.speedy
#----------------------------------------------------------------------
def update(self):
""""""
self.image = self.imagelist[self.frame]
if self.timer >= self.timerlimit:
self.frame += 1
if self.frame >= len(self.imagelist):
self.frame = 0
self.timer = 0
self.timer += 1
plat = pygame.image.load("plt0.png").convert_alpha()
star = pygame.image.load("gemp0.png").convert_alpha()
#box = pygame.image.load("crateB.png").convert_alpha()
platforms = pygame.sprite.Group()
boxes = pygame.sprite.Group()
rotcenx = SCREENW/2
rotceny = SCREENH/2
radius = 200
angle = radians(90) #pi/4 # starting angle 45 degrees
omega = radians(5) #Angular velocity
m = rotcenx + radius * cos(angle) #Starting position x
n = rotceny - radius * sin(angle) #Starting position y
for _ in itertools.repeat(None, 1):
madyax = SCREENW/2
madyay = SCREENH/2
araya = 200
konaya = radians(180) #pi/4 # starting angle 45 degrees
konika_pravegaya = radians(5) #Angular velocity
a = madyax + (araya * cos(konaya)) #Starting position x
b = madyay - (araya * sin(konaya)) #Startinh position y
plat = object_factory([plat], a, b)
plat.araya = araya
plat.konaya = konaya
plat.kp = konika_pravegaya
platforms.add(plat)
while True:
ms = clock.tick(FPS) # milliseconds passed since last frame
#looptime = milliseconds / 1000.0 # seconds passed since last frame
SCREEN.fill((BLACK))
pygame.draw.circle(SCREEN, BLUE, (SCREENW / 2, SCREENH / 2), 5)
##-----------------------------------------------------------
SCREEN.blit(star, (m, n)) # Draw current x,y
angle = angle + omega # New angle, we add angular velocity
m = m + radius * omega * cos(angle + pi / 2) # New x
n = n - radius * omega * sin(angle + pi / 2) # New y
##-----------------------------------------------------------
# show object anchored to center of rotation
pygame.draw.line(SCREEN, ORANGE, (rotcenx, rotceny), (m, n))
text = maketext(str(radius), 30)
SCREEN.blit(text, (m, n - 40))
text = maketext((str(round(m, 2)) + " " + str(round(n, 2))), 30)
SCREEN.blit(text, (m, n + 40)) # Draw current x,y
##------------------------------------------------------------------
for plat in platforms:
plat.konaya = plat.konaya + plat.kp
plat.rect.x = plat.rect.x + plat.araya * plat.kp * cos(plat.konaya + pi / 2)
plat.rect.y = plat.rect.y - plat.araya * plat.kp * sin(plat.konaya + pi / 2)
##------------------------------------------------------------------------
pygame.draw.line(SCREEN, ORANGE, (madyax, madyay), (plat.rect.x, plat.rect.y))
platforms.update()
platforms.draw(SCREEN)
pygame.event.pump()
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
pygame.display.update()
pygame.time.wait(100)
Why does the code work when used outside a class and NOT when in? I simply can't find what I have done wrong.
Please don't ask me to read any Google documents or search on the Internet as I am posting after doing so and NOT finding an answer to my question. I am NOT an expert in math and would only like to know a solution to this problem. Please help.
Link to video is below
http://youtu.be/0oRDX246aj8

Related

Pygame sprites disappears [duplicate]

This question already has answers here:
How can I add objects to a "pygame.sprite.Group()"?
(1 answer)
What does pygame.sprite.Group() do
(1 answer)
When I use pygame.sprite.spritecollide(), why does only the bullets disappear?
(1 answer)
Closed 2 months ago.
I'm working on a doom style game that uses RayCasting and sprites objects. But my sprites disappears after the player turns right side around the image.
This is video with my problem:https://www.youtube.com/watch?v=oWBGlVdpGSg
I tried shrinking the image and also editing them with ImageMagick Display. Nothing helped and I'm desperate.
I follow this video: https://youtu.be/ECqUrT7IdqQ?t=1480
And here is my code (sprite objects):
import pygame as pg
from settings import *
import os
from collections import deque
class SpriteObject:
def __init__(self, game, path="resources/sprites/static_sprites/candlebra.png",
pos=(10.5, 3.5), scale=0.7, shift=0.27):
self.game = game
self.player = game.player
self.x, self.y = pos
self.image = pg.image.load(path).convert_alpha()
self.IMAGE_WIDTH = self.image.get_width()
self.IMAGE_HALF_WIDTH = self.image.get_width() // 2
self.IMAGE_RATIO = self.IMAGE_WIDTH / self.image.get_height()
self.dx, self.dy, self.theta, self.screen_x, self.dist, self.norm_dist = 0, 0, 0, 0, 1, 1
self.sprite_half_width = 0
self.SPRITE_SCALE = scale
self.SPRITE_HEIGHT_SHIFT = shift
def get_sprite_projection(self):
proj = SCREEN_DIS / self.norm_dist * self.SPRITE_SCALE
proj_width, proj_height = proj * self.IMAGE_RATIO, proj
image = pg.transform.scale(self.image, (proj_width, proj_height))
self.sprite_half_width = proj_width // 2
height_shift = proj_height * self.SPRITE_HEIGHT_SHIFT
pos = self.screen_x - self.sprite_half_width, HALF_HEIGHT - proj_height // 2 + height_shift
self.game.raycasting.objects_to_render.append((self.norm_dist, image, pos))
def get_sprite(self):
dx = self.x - self.player.x
dy = self.y - self.player.y
self.dx, self.dy = dx, dy
self.theta = math.atan2(dy, dx)
delta = self.theta - self.player.angle
if (dx > 0 and self.player.angle > math.pi) or (dx < 0 and dy < 0):
delta += math.tau
delta_rays = delta / DELTA_ANGLE
self.screen_x = (HALP_NUM_RAYS + delta_rays) * SCALE
self.dist = math.hypot(dx, dy)
self.norm_dist = self.dist * math.cos(delta)
if -self.IMAGE_HALF_WIDTH < self.screen_x < (WIDTH + self.IMAGE_HALF_WIDTH) and self.norm_dist > 0.9:
self.get_sprite_projection()
def update(self):
self.get_sprite()
class AnimatedSprites(SpriteObject):
def __init__(self, game, path="resources/sprites/animated_sprites/green_light/0.png",
pos=(11.5, 3.5), scale=0.8, shift=0.15, animation_time=120):
super().__init__(game, path, pos, scale, shift)
self.animation_time = animation_time
self.path = path.rsplit("/", 1)[0]
self.images = self.get_images(self.path)
self.animation_time_prev = pg.time.get_ticks()
self.animation_trigger = False
def update(self):
super().update()
self.check_animation_time()
self.animate(self.images)
def animate(self, images):
if self.animation_trigger:
images.rotate(-1)
self.image = images[0]
def check_animation_time(self):
self.animation_trigger = False
time_now = pg.time.get_ticks()
if time_now - self.animation_time_prev > self.animation_time:
self.animation_time_prev = time_now
self.animation_trigger = True
def get_images(self, path):
images = deque()
for file_name in os.listdir(path):
if os.path.isfile(os.path.join(path, file_name)):
img = pg.image.load(path + "/" + file_name).convert_alpha()
images.append(img)
return images
Here is main :
import pygame as pg
import sys
from settings import *
from map import *
from player import *
from raycasting import *
from object_renderer import *
from sprite_object import *
from object_handler import *
class Game:
def __init__(self):
pg.init()
pg.mouse.set_visible(False)
self.screen = pg.display.set_mode(RES)
self.clock = pg.time.Clock()
self.delta_time = 1
self.new_game()
def new_game(self):
self.map = Map(self)
self.player = Player(self)
self.object_renderer = ObjectRenderer(self)
self.raycasting = RayCasting(self)
self.object_handler = ObjectHandler(self)
def update(self):
self.player.update()
self.raycasting.update()
self.object_handler.update()
pg.display.flip()
self.delta_time = self.clock.tick(FPS)
pg.display.set_caption(f"{self.clock.get_fps()} :.1f")
def draw(self):
#self.screen.fill("black")
self.object_renderer.draw()
# self.map.draw()
# self.player.draw()
def check_events(self):
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
pg.quit()
sys.exit()
def run(self):
while True:
self.check_events()
self.update()
self.draw()
if __name__ == "__main__":
game = Game()
game.run()

Python 2d Raycaster not using proper depth [duplicate]

This question already has answers here:
How do I fix wall warping in my raycaster?
(1 answer)
Problem with recognising where a ray in raycaster intersects a wall along the horizontal axis
(1 answer)
cant get raycast to work from angles 90 to 270 pygame
(1 answer)
Why my raycasting keeps going through walls?
(1 answer)
Closed 3 months ago.
I am trying to create a raycast visualizer. The lines are supposed to shoot out and stop when they collide with a wall. Currently the length is entirely random and sometimes the rays point in directions that are even behind me. I am using an scale of 47 when i draw things to the screen for tiling purposes. I have tried for 10 or so hours every scale in the raycast code and I can't see what I am missing.
import pygame
import numpy
from PygameEngine import GameEngine
import sys
import math
class RayCasting:
FOV = numpy.pi/5
HALF_FOV = FOV/2
NUM_RAYS = GameEngine.WIDTH//2
HALF_NUM_RAYS = NUM_RAYS//2
DELTA_ANGLE = FOV/NUM_RAYS
MAX_DEPTH = 20
def __init__(self, game):
self.game = game
def rayCast(self):
ox, oy = self.game.wasd.pos
x_map = int(ox)
y_map = int(oy)
ray_angle = self.game.wasd.angle - self.HALF_FOV + 0.000001
for ray in range(self.NUM_RAYS):
sin_a = math.sin(ray_angle)
cos_a = math.cos(ray_angle)
# horizontals
y_hor, dy = (y_map + 1, 1) if sin_a > 0 else (y_map - 1e-6, -1)
depth_hor = (y_hor - oy) / sin_a
x_hor = ox + depth_hor * cos_a
delta_depth = dy / sin_a
dx = delta_depth * cos_a
print("YHor: ",y_hor, " DY:", dy, " Depth Hor: ", depth_hor, "X Hor: ", x_hor,
" Delta Depth: ", delta_depth, " DX: ", dx)
for i in range(self.MAX_DEPTH):
tile_hor = int(x_hor), int(y_hor)
if tile_hor in self.game.MAP.wallMap:
# print("INSIDE HOR")
break
x_hor += dx
y_hor += dy
depth_hor += delta_depth
# verticals
x_vert, dx = (x_map + 1, 1) if cos_a > 0 else (x_map - 1e-6, -1)
depth_vert = (x_vert - ox) / cos_a
y_vert = oy + depth_vert * sin_a
delta_depth = dx / cos_a
dy = delta_depth * sin_a
for i in range(self.MAX_DEPTH):
tile_vert = int(x_vert), int(y_vert)
if tile_vert in self.game.MAP.wallMap:
# print("INSIDE VERT")
break
x_vert += dx
y_vert += dy
depth_vert += delta_depth
# depth, texture offset
if depth_vert < depth_hor:
depth = depth_vert
#y_vert %= 1
#offset = y_vert if cos_a > 0 else (1 - y_vert)
else:
depth = depth_hor
#x_hor %= 1
#offset = (1 - x_hor) if sin_a > 0 else x_hor
# remove fishbowl effect
#depth *= math.cos(self.game.wasd.angle - ray_angle)
# projection
#proj_height = SCREEN_DIST / (depth + 0.0001)
# ray casting result
#self.ray_casting_result.append((depth, proj_height, texture, offset))
ray_angle += self.DELTA_ANGLE
pygame.draw.line(self.game.screen, "yellow", (ox*self.game.CELLSIZE,oy*self.game.CELLSIZE), (ox*self.game.CELLSIZE+depth*cos_a, oy*self.game.CELLSIZE+depth*sin_a), 1)
def update(self):
self.rayCast()
from PygameEngine import GameEngine
from Circle import Circle
import pygame
from pygame.locals import *
import sys
import numpy
from map import Map
from RaycastFunction import RayCasting
class RaycastGame(GameEngine):
# Space bar to place this circle which will connect to the WASD with a line
planet = Circle((0,0,0))
planet.keyX = 5
planet.keyY = 5
# Grid set up
def __init__(self):
super().__init__()
self.load()
self.MAP = Map()
self.CELLSIZE = self.MAP.CELLSIZE
# Circle controllable with WASD
self.wasd = Circle((123, 255, 123))
self.raycast = RayCasting(self)
def DDA(self):
# -
# * |
# Remember the Plane is - --m-- +
# * = target |
# m = mouse +
distX = self.wasd.keyX - self.planet.pos[0]
distY = self.wasd.keyY - self.planet.pos[1]
#hypotenuse = numpy.sqrt(distX**2+distY**2)
theta = numpy.arctan((distY/(distX+.0001)))
theta += numpy.deg2rad(90)
# print(numpy.rad2deg(theta), " THETA")
collisionPos = (0,0)
def draw(self):
# Draw MAP array
self.MAP.drawMap()
self.MAP.drawGrid()
# Draw mouse character
#pygame.draw.circle(self.screen, (0, 0, 0),
#(self.plane), Circle.radius)
# Draw planet
# self.planet.draw(self.screen)
# Draw wasd character
self.wasd.draw(self.screen)
# Connect mouse and wasd characters with a line
#pygame.draw.line(self.screen, (255, 255, 255), self.planet.pos, (self.wasd.keyX, self.wasd.keyY), 5)
def update(self):
self.planet.placePlanet()
self.wasd.move()
self.DDA()
self.raycast.update()
def run(self):
# Game loop.
while True:
#This gets written over. Only for clearing screen before each draw
self.screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# Update.
self.update()
# Draw
self.draw()
pygame.display.flip()
self.fpsClock.tick(self.FPS)
I do not understand why the rays are not stopping in the proper area.

Pygame: Moving an image around another image in a circular path

I know that there are already some solutions here but unfortunately they did not help me with my problem. I want to move a satellite image around a planet image in a circular path. I know how to move it in a line from left to right but I don't get it how to make the circle. This is my code so far
import pygame
from pygame.locals import *
from sys import exit
from math import sin
from math import cos
player_image = 'dragon-500px.png'
pygame.init()
screen = pygame.display.set_mode((1080, 720), 0, 32)
pygame.display.set_caption("Animate X!")
mouse_cursor = pygame.image.load(player_image).convert_alpha()
image_earth = pygame.image.load('Erde.jpg').convert()
image_earth = pygame.transform.scale(image_earth, (300,300))
image_earth_rect = image_earth.get_rect()
image_earth_rect.center = (540, 360)
radius = 100
center = (540, 360)
direction = pygame.math.Vector2(1,0)
clock = pygame.time.Clock()
speed = 300.0
x = 0 - mouse_cursor.get_width()
y = 10
while True:
time_passed = clock.tick() / 1000.0
moved_distance = time_passed * speed
for event in pygame.event.get():
if event.type == QUIT:
exit()
direction.rotate_ip(4)
direction.normalize_ip()
Satellite_pos = [int(i) for i in center + direction*radius]
screen.fill((255,255,255))
if x > screen.get_width():
x = 0 - mouse_cursor.get_width()
elif y > screen.get_height():
y = 10
screen.blit(mouse_cursor, (x, y))
screen.blit(image_earth, image_earth_rect)
x+=moved_distance
y+= moved_distance
pygame.display.update() ```
Compute the position of the satellite dependent on an angle:
angle = 0
# [...]
while True:
# [...]
center = image_earth_rect.center
Satellite_pos = [center[0] + radius * cos(angle), center[1] + radius * sin(angle)]
angle += 0.01
# [...]

How to draw a Spiral & Arc Shape Curves using pygame? [duplicate]

I am trying to make realistic water in pygame:
This is till now my code:
from random import randint
import pygame
WIDTH = 700
HEIGHT = 500
win = pygame.display.set_mode((WIDTH, HEIGHT))
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
AQUA = 'aqua'
RADIUS = 1
x, y = 0, HEIGHT//2
K = 1
FORCE = 100
VELOCITY = 0.5
run = True
class Molecule:
def __init__(self, x, y, radius, force, k):
self.x = x
self.y = y
self.radius = radius
self.force = force
self.k = k
self.max_amplitude = y + force/k
self.min_amplitude = y - force/k
self.up = False
self.down = True
self.restore = False
def draw(self, win):
pygame.draw.circle(win, BLACK, (self.x, self.y), self.radius)
def oscillate(self):
if self.y <= self.max_amplitude and self.down == True:
self.y += VELOCITY
if self.y == self.max_amplitude or self.up:
self.up = True
self.down = False
self.y -= VELOCITY
if self.y == self.min_amplitude:
self.up = False
self.down = True
molecules = []
for i in range(100):
FORCE = randint(10, 20)
molecules.append(Molecule(x, y, RADIUS, FORCE, K))
x += 10
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
win.fill(WHITE)
for molecule in molecules:
molecule.draw(win)
molecule.oscillate()
for i in range(len(molecules)):
try:
pygame.draw.line(win, BLACK, (molecules[i].x, molecules[i].y), (molecules[i+1].x, molecules[i+1].y))
pygame.draw.line(win, AQUA, (molecules[i].x, molecules[i].y), (molecules[i+1].x, HEIGHT))
except:
pass
pygame.display.flip()
pygame.quit()
But as may expected the water curve is not smooth:
Look at it:
Sample Img1
I want to connect the two randomly added wave points using a set of circles not line like in this one so that a smooth curve could occur.
And in this way i could add the water color to it such that it will draw aqua lines or my desired color line from the point to the end of screen and all this will end up with smooth water flowing simulation.
Now the question is how could i make the points connect together smoothly into a smooth curve by drawing point circles at relative points?
I suggest sticking the segments with a Bézier curves. Bézier curves can be drawn with pygame.gfxdraw.bezier
Calculate the slopes of the tangents to the points along the wavy waterline:
ts = []
for i in range(len(molecules)):
pa = molecules[max(0, i-1)]
pb = molecules[min(len(molecules)-1, i+1)]
ts.append((pb.y-pa.y) / (pb.x-pa.x))
Use the the tangents to define 4 control points for each segment and draw the curve with pygame.gfxdraw.bezier:
for i in range(len(molecules)-1):
p0 = molecules[i].x, molecules[i].y
p3 = molecules[i+1].x, molecules[i+1].y
p1 = p0[0] + 10, p0[1] + 10 * ts[i]
p2 = p3[0] - 10, p3[1] - 10 * ts[i+1]
pygame.gfxdraw.bezier(win, [p0, p1, p2, p3], 4, BLACK)
Complete example:
from random import randint
import pygame
import pygame.gfxdraw
WIDTH = 700
HEIGHT = 500
win = pygame.display.set_mode((WIDTH, HEIGHT))
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
AQUA = 'aqua'
RADIUS = 1
x, y = 0, HEIGHT//2
K = 1
FORCE = 100
VELOCITY = 0.5
class Molecule:
def __init__(self, x, y, radius, force, k):
self.x = x
self.y = y
self.radius = radius
self.force = force
self.k = k
self.max_amplitude = y + force/k
self.min_amplitude = y - force/k
self.up = False
self.down = True
self.restore = False
def draw(self, win):
pygame.draw.circle(win, BLACK, (self.x, self.y), self.radius)
def oscillate(self):
if self.y <= self.max_amplitude and self.down == True:
self.y += VELOCITY
if self.y == self.max_amplitude or self.up:
self.up = True
self.down = False
self.y -= VELOCITY
if self.y == self.min_amplitude:
self.up = False
self.down = True
molecules = []
for i in range(50):
FORCE = randint(10, 20)
molecules.append(Molecule(x, y, RADIUS, FORCE, K))
x += 20
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
win.fill(WHITE)
for molecule in molecules:
molecule.draw(win)
molecule.oscillate()
ts = []
for i in range(len(molecules)):
pa = molecules[max(0, i-1)]
pb = molecules[min(len(molecules)-1, i+1)]
ts.append((pb.y-pa.y) / (pb.x-pa.x))
for i in range(len(molecules)-1):
p0 = molecules[i].x, molecules[i].y
p3 = molecules[i+1].x, molecules[i+1].y
p1 = p0[0] + 10, p0[1] + 10 * ts[i]
p2 = p3[0] - 10, p3[1] - 10 * ts[i+1]
pygame.gfxdraw.bezier(win, [p0, p1, p2, p3], 4, BLACK)
for i in range(len(molecules)-1):
pygame.draw.line(win, AQUA, (molecules[i].x, molecules[i].y), (molecules[i].x, HEIGHT))
pygame.display.flip()
pygame.quit()
If you want to "fill" the water, you must calculate the points along the Bézier line and draw a filled polygon. How to calculate a Bézier curve is explained in Trying to make a Bezier Curve on PyGame library How Can I Make a Thicker Bezier in Pygame? and "X". You can use the following function:
def ptOnCurve(b, t):
q = b.copy()
for k in range(1, len(b)):
for i in range(len(b) - k):
q[i] = (1-t) * q[i][0] + t * q[i+1][0], (1-t) * q[i][1] + t * q[i+1][1]
return round(q[0][0]), round(q[0][1])
def bezier(b, samples):
return [ptOnCurve(b, i/samples) for i in range(samples+1)]
Use the bezier to stitch the wavy water polygon:
ts = []
for i in range(len(molecules)):
pa = molecules[max(0, i-1)]
pb = molecules[min(len(molecules)-1, i+1)]
ts.append((pb.y-pa.y) / (pb.x-pa.x))
pts = [(WIDTH, HEIGHT), (0, HEIGHT)]
for i in range(len(molecules)-1):
p0 = molecules[i].x, molecules[i].y
p3 = molecules[i+1].x, molecules[i+1].y
p1 = p0[0] + 10, p0[1] + 10 * ts[i]
p2 = p3[0] - 10, p3[1] - 10 * ts[i+1]
pts += bezier([p0, p1, p2, p3], 4)
Draw the polygon with pygame.draw.polygon():
pygame.draw.polygon(win, AQUA, pts)
Complete example:
from random import randint
import pygame
class Node:
def __init__(self, x, y, force, k, v):
self.x = x
self.y = y
self.y0 = y
self.force = force
self.k = k
self.v = v
self.direction = 1
def oscillate(self):
self.y += self.v * self.direction
if self.y0 - self.force / self.k > self.y or self.y0 + self.force / self.k < self.y:
self.direction *= -1
def draw(self, surf):
pygame.draw.circle(surf, "black", (self.x, self.y), 3)
window = pygame.display.set_mode((700, 500))
clock = pygame.time.Clock()
width, height = window.get_size()
no_of_nodes = 25
dx = width / no_of_nodes
nodes = [Node(i*dx, height//2, randint(15, 30), 1, 0.5) for i in range(no_of_nodes+1)]
def ptOnCurve(b, t):
q = b.copy()
for k in range(1, len(b)):
for i in range(len(b) - k):
q[i] = (1-t) * q[i][0] + t * q[i+1][0], (1-t) * q[i][1] + t * q[i+1][1]
return round(q[0][0]), round(q[0][1])
def bezier(b, samples):
return [ptOnCurve(b, i/samples) for i in range(samples+1)]
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
for molecule in nodes:
molecule.oscillate()
ts = []
for i in range(len(nodes)):
pa = nodes[max(0, i-1)]
pb = nodes[min(len(nodes)-1, i+1)]
ts.append((pb.y-pa.y) / (pb.x-pa.x))
pts = [(width, height), (0, height)]
for i in range(len(nodes)-1):
p0 = nodes[i].x, nodes[i].y
p3 = nodes[i+1].x, nodes[i+1].y
p1 = p0[0] + 10, p0[1] + 10 * ts[i]
p2 = p3[0] - 10, p3[1] - 10 * ts[i+1]
pts += bezier([p0, p1, p2, p3], 4)
window.fill("white")
pygame.draw.polygon(window, 'aqua', pts)
for molecule in nodes:
molecule.draw(window)
pygame.display.flip()
pygame.quit()
exit()

Python: pygame deleting image on mouse click and creating it again

im trying to make a simple game where the there are soldiers coming towards you and when you click them to "kill" them they go at the back of the screen and start to come towards you, so on.....
however i'm having trouble with pygame mouse click event and it just doesnt work.
heres my code so far:
import pygame, math
from random import randrange
import sys, math, pygame
from operator import itemgetter
def getKey(customobj):
return customobj.getKey()
class Point3D:
def __init__(self, imfiles, nfrm, x = 0, y = 0, z = 0):
self.x, self.y, self.z = float(x), float(y), float(z)
self.frms = []
self.nfrm=nfrm
self.index=0
for k in range(0,nfrm):
im=pygame.image.load(imfiles+'_'+str(k+1)+'.png')
im.set_colorkey((0,0,0))
self.frms.append(im)
def
project(self, win_width, win_height, fov, viewer_distance):
""" Transforms this 3D point to 2D using a perspective projection. """
factor = fov / (viewer_distance + self.z)
x = self.x * factor + win_width / 2
y = -self.y * factor + win_height / 2
return Point3D(x, y, self.z)
def draw3D(self, wsurface, fov, viewer_distance, max_depth):
win_width=wsurface.get_width()
win_height=wsurface.get_height()
factor = fov / (viewer_distance + self.z)
x = self.x * factor + win_width / 2
y = -self.y * factor + win_height / 2
size = int((1 - float(self.z) / max_depth) * 64)
im=pygame.transform.smoothscale(self.frms[self.index],(size,size))
try:
wsurface.blit(im, (x, y))
except:
print((x,y))
self.index=self.index+1
if self.index >= self.nfrm:
self.index=0
def getKey(self):
return -self.z
class StartField:
def __init__(self, num_stars, max_depth):
pygame.init()
myWin = pygame.display.set_mode((640, 450), 0, 32)
pygame.display.set_caption('Drawing')
self.screen = myWin.subsurface([0,0,640,400]);
self.txtwin = myWin.subsurface([0,400,640,50]);
pygame.display.set_caption("Task C")
self.clock = pygame.time.Clock()
self.num_stars = num_stars
self.max_depth = max_depth
self.init_stars()
def init_stars(self):
""" Create the starfield """
self.stars = []
for i in range(self.num_stars):
# A star is represented as a list with this format: [X,Y,Z]
star = Point3D('im',8,randrange(-25,25), randrange(-25,25), randrange(1, self.max_depth))
self.stars.append(star)
def move_and_draw_stars(self):
""" Move and draw the stars """
origin_x = self.screen.get_width() / 2
origin_y = self.screen.get_height() / 2
stars=sorted(self.stars,key = getKey)
for star in stars:
# The Z component is decreased on each frame.
star.z -= 0.05
# If the star has past the screen (I mean Z<=0) then we
# reposition it far away from the screen (Z=max_depth)
# with random X and Y coordinates.
if star.z <= 0:
star.x = randrange(-25,25)
star.y = randrange(-25,25)
star.z = self.max_depth
# Convert the 3D coordinates to 2D using perspective projection.
star.draw3D(self.screen, 128, 0, self.max_depth)
def run(self):
""" Main Loop """
bgPicture = pygame.transform.smoothscale(pygame.image.load('Starfield.jpg'),(self.screen.get_width(),self.screen.get_height()))
font = pygame.font.Font(None, 36)
while 1:
# Lock the framerate at 50 FPS.
self.clock.tick(50)
# Handle events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
self.screen.blit(bgPicture, [0,0])
self.move_and_draw_stars()
# Text window outputs
self.txtwin.fill([200,200,200])
text = font.render("Total Score: ", 1, (10, 10, 10))
self.txtwin.blit(text, [5, 5])
pygame.display.update()
if __name__ == "__main__":
StartField(256, 24).run()
pygame.init()
pygame.mixer.init()
sounda= pygame.mixer.Sound("MuseUprising.mp3")
sounda.play()
To test for the left mouse button:
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
If give the soldier a pygame.Rect you can use that to check for collision with the mouse pointer like this:
mouse_pos = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0] and self.rect.collidepoint(mouse_pos):

Categories