简体   繁体   中英

pygame - KEYDOWN event - line not updating position

I am making a 2-player game which is supposed to look like:
游戏形象
In the game, the shooters(green and blue, controlled by players) can shoot bullets at each other.
If the bullet
1. collides with the wall(grey), it gets destroyed.
2. hits the shooter, it loses health(shooter).
The game is (supposed to be) turn-based and ends when a player reaches 0 health.

My Problem(s)
1. The barrel of my shooters is not updating/rotating.
2. Is there a better way to detect if a(ny) key is pressed.
* Shooter,Bullet,Wall are classes

My code
(comment if any function that would be useful in answering is not mentioned)

import math,random,pygame
def event_handle(event,turn):
    if turn == 1:
        c_s = p1
    elif turn == 2:
        c_s = p2
    else:
        return None
    if event.type == pygame.KEYDOWN:
        key = pygame.key.get_pressed()
        # next_pos
        if key[pygame.K_q]:
            c_s.next_x -= 1
        if key[pygame.K_e]:
            c_s.next_x += 1
        # angle
        if key[pygame.K_w]:
            c_s.angle += radians(1)
        if key[pygame.K_s]:
            c_s.angle -= radians(1)
        # power (speed)
        if key[pygame.K_d]:
            c_s.speed += 0.1
        if key[pygame.K_a]:
            c_s.speed -= 0.1

def draw_all(bullist,shooters,wall,surface):
    # draw shooters
    for shooter in shooters:
        shooter.move()
        shooter.draw(surface)
    # draw bullets
    for bullet in bullist:
        bullet.gravity()
        bullet.move()
        bullet.collides(shooters,wall,bullist)
        bullet.out(surface,bullist)
        bullet.draw(surface)
    # wall
    wall.update()
    wall.draw(surface)
    pygame.draw.aaline(surface,(255,255,255),(0,400),(640,400))

def angle(A,B,BC,theta):

    C = [0,0]
    alpha = math.atan2(A[1]-B[1] , A[0] -B[0] ) - theta
    C[0] = int(round(B[0]  + BC * math.cos(alpha),0))
    C[1] = int(round(B[1]  + BC * math.sin(alpha),0))
    return C

class Shooter:
    def __init__(self,pos,size,color,xmax,xmin):
        self.pos = pos
        self.size = size
        self.rect = pygame.Rect(pos,size)
        self.health = 100
        self.color = color
        self.angle = 0
        self.speed = 0
        self.max = xmax
        self.min = xmin
        self.next_x = pos[0]

        self.color2 = []
        for i in color:
            i = i - 100
            if i < 0:
                i = 0
            self.color2.append(i)

    def draw(self,surface):
        global C
        pygame.draw.rect(surface,self.color,self.rect)

        c = angle(self.rect.midleft,self.rect.center,
                  20,radians(self.angle))
        if c != C and c != [95,392]:
            print c
            C = c
        pygame.draw.line(surface,self.color2,self.rect.center,c,3)


## the other funcs or classes not needed

# globals
turn = 1
C = []
# pygame
(width, height) = (640, 480)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Shooter')
clock = pygame.time.Clock()
# game actors
shooters = []
bullets = []
p1 = Shooter((400,400),(30,-15),(255,0,0),0,0)
p2 = Shooter((100,400),(30,-15),(0,255,0),0,0)
shooters.extend([p1, p2])
wall = Wall(100)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            pygame.quit()
            break
        else: event_handle(event,turn)
    if not running:
        break
    screen.fill((0,0,0))
    # Game draw logic + Game logic

    draw_all(bullets,shooters,wall,screen)
    pygame.display.flip()
    clock.tick(40)

What am I doing wrong?

Your code actually works, but there are some problems. The barrels actually rotate, but only a very small amount on every key press.

Try and change your event_handle function to this:

def event_handle(turn):
    if turn == 1:
        c_s = p1
    elif turn == 2:
        c_s = p2
    else:
        return None
    key = pygame.key.get_pressed()
    # next_pos
    if key[pygame.K_q]:
        c_s.next_x -= 1
    if key[pygame.K_e]:
        c_s.next_x += 1
    # angle
    if key[pygame.K_w]:
        c_s.angle += radians(10)
    if key[pygame.K_s]:
        c_s.angle -= radians(10)
    # power (speed)
    if key[pygame.K_d]:
        c_s.speed += 0.1
    if key[pygame.K_a]:
        c_s.speed -= 0.1

Since you are not interessed in the event type at all at this point, I removed the event parameter and the if event.type == pygame.KEYDOWN: check. This way, you can keep your keys pressed instead of being forced to hit the keys multiple times to rotate the barrels.

I also increased the value the barrels rotate from radians(1) to radians(10) . Otherwise, the change is too small to be visible (in a reasonable amount of time).

Also, you have to adjust your main loop to

...
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
        pygame.quit()
        break
if not running:
    break
event_handle(turn)
...

so event_handle is called every iteration of the main loop.

If you are using key.get_pressed you don't need to detect the key_down event at all. Just remove the if event.type == pygame.KEYDOWN: statement, and go checking if what is returned from pygame.key.get_pressed have your keys.

Alos, you should be calling pygame.event.pump somewhere in your code, at every loop run. Put it inside your while loop.

(And a tip not related with your problem: move that main loop inside a function - it is just hideous to have it hanging in the program body like this)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM