-1

I was looking for the reason for about 3 hours, but I could not find any solution.

There is no error but the program does not seem to detect my key input. also, I don't see what is wrong with my code.

Additionally, I don't think I understood how event.key and pygame.event.get() is operating. I would be very appreciated if someone explains it to me.

And this is code from my Ascii game, and it's just a beginning of the code, which I've done so far.

    class maingame:

    def __init__(self):
        exit = False

    def processkey(self):
        global hotkey,crazy

        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == K_SPACE:
                    crazy = 1
                if event.key == K_DOWN:
                    dir = 's'
                    y_option -= 1
                    hotkey  = 2
                if event.key == pygame.K_w:
                    dir = 'w'
                    y_option += 1
                    hotkey = 1
                if event.key == K_LEFT:
                    dir = 'a'

                if event.key == K_RIGHT:
                    dir = 'd'
            else:
                    hotkey = 1
                    y_option = 0
                    crazy = 0

    def displaymanu(self,hotkey):
        print(">" if hotkey == 1 else " ","play")
        print(">" if hotkey == 2 else " ","quit")
        if hotkey == 1 and crazy == 1:
            self.play()     
        elif hotkey == 2 and crazy == 1:
            exit = True
if __name__ == '__main__':
        while not quit:
            displayee = maingame()
            os.system('cls')
            displayee.processkey()
            displayee.processkey()
            displayee.displaymanu(hotkey)
  • Sorry, I can't figure out what you're actually trying to do in your code..... Could you explain what you expect to happen? – sloth Mar 19 '19 at 15:37
  • Where is your `pygame.init()`? And you shouldn't re-create your `maingame()` class every loop. That will break a lot of things. – Torxed Mar 19 '19 at 16:45
  • 1
    Further more, where do you setup your main screen? This code will give `pygame.error: video system not initialized`. And the reason why this isn't working is because Pygame is a **graphical library**. It won't do ASCII at all. [here](https://stackoverflow.com/questions/3523174/raw-input-in-python-without-pressing-enter) is a alternative for ASCII stuff. If that's not to your liking - I can post a ASCII OpenGL version below where the ASCII appears in a graphical window. But you won't get what you need from Pygame in this case. – Torxed Mar 19 '19 at 16:51

2 Answers2

1

PyGame will not work without a screen/window. So your code needs to first initialise PyGame, and then open a window (or full-screen display).

From my understanding of your code, it looks like it should display a menu:

> Play
  Quit

Where pressing / (or w/s) moves the > cursor between the options, and then space runs the option.

One of the issues with your code, is your trying to interpret the key-strokes inside the displaymanu() function. It's best to keep a function doing a singular thing, so all key handling in processkey() and only screen drawing in displaymanu().

I patched your code to the point where it works. This involved modifying the class so that it initialised the PyGame display. The menu needed to be displayed in the window, so calls to a new function drawTextAt() were added in place of the print(). Many of the member variables of class Maingame had scope issues, but simply specifying self.variable-name (which made them members of the class) fixed these.

I also added a game state to show how the key handling needs to change depending on what phase the game is currently in. It starts in menu, where Up/Down simply changes the menu option. But then later during the game play, Up/Down needs to do something entirely different.

import pygame
import os

# Window size
WINDOW_WIDTH  = 400
WINDOW_HEIGHT = 400
# colours
DARK    = (  50, 50, 50 )
RED     = ( 255, 50, 50 )


class Maingame:

    def __init__(self):
        # Initialise PyGame
        pygame.init()
        pygame.font.init()
        # Initialise a window
        pygame.display.set_caption("Main Game")
        self.screen = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.DOUBLEBUF )
        # menu font
        self.font   = pygame.font.SysFont(None, 20)

        self.hotkey     = 1
        self.crazy      = 0
        self.y_option   = 0
        self.game_state = 0  # state=0 -> show menu, 1 => Game, 2-> Game Over

    def processkey(self):
        # no key pressed yet
        self.crazy = 0
        dir_code   = ''  
        exit       = False

        # Detect keys pressed
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    dir_code = ' '
                    self.crazy = 1
                elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
                    dir_code = 's'
                    self.y_option -= 1
                    self.hotkey  = 2
                elif event.key == pygame.K_w or event.key == pygame.K_UP:
                    dir_code = 'w'
                    self.y_option += 1
                    self.hotkey = 1
                elif event.key == pygame.K_LEFT:
                    dir_code = 'a'
                elif event.key == pygame.K_RIGHT:
                    dir_code = 'd'
                else:
                    self.hotkey = 1
                    self.y_option = 0
                    self.crazy = 0
                print( "DEBUG - game_state=[%d], dir_code is [%s], hotkey is [%d], crazy=[%d]" % ( self.game_state, dir_code, self.hotkey, self.crazy ) )

                # Act on the keys pressed (if any)
                if self.game_state == 0:  # menu mode
                    if self.hotkey == 1 and self.crazy == 1:
                        self.game_state = 1 # start the game
                    elif self.hotkey == 2 and self.crazy == 1:
                        exit = True
                elif self.game_state == 1:  # game mode
                    pass  # TODO
                elif self.game_state == 2:  # game-over mode
                    pass  # TODO

        return exit

    def drawTextAt( self, text, coord, foreground_colour=(255,255,255) ):
        """ Convert the specified text into a font-bitmap, and draw it
            onto the screen at the given co-ordinates """
        text_bitmap = self.font.render( text, True, foreground_colour )
        self.screen.blit( text_bitmap, coord )

    def displaymanu( self ):
        """ Draw the Menu """
        # MENU
        self.screen.fill( DARK )
        # Draw the menu options
        prefix = [ "  ", "  " ]
        prefix[ self.hotkey-1 ] = "> "
        self.drawTextAt( prefix[0] + "Play", ( 30, 100 ) )
        self.drawTextAt( prefix[1] + "Quit", ( 30, 150 ) )


    def displaygame( self ):
        """ Draw the Game Screen """
        # GAME SCREEN
        self.screen.fill( RED )
        self.drawTextAt( "GAME - #TODO", ( 30, 180 ) )

    def displaygameover( self ):
        """ Draw the Game-Over Screen """
        # GAME OVER SCREEN
        self.screen.fill( RED )
        self.drawTextAt( "* GAME OVER *", ( 30, 180 ) )

if __name__ == '__main__':
    # Initialise PyGame and the window

    displayee = Maingame()
    quit = False
    while not quit:
        #os.system('cls')
        # Draw the correct display for the state
        if displayee.game_state == 0:
            displayee.displaymanu()
        elif displayee.game_state == 1:
            displayee.displaygame()
        elif displayee.game_state == 2:
            displayee.displaygameover()
        # Push all drawing to the screen
        pygame.display.flip()
        # Handle keys
        quit = displayee.processkey()
Kingsley
  • 14,398
  • 5
  • 31
  • 53
  • Great answer! And a proper answer with a lot of work behind it. I can't decide if you're my nemesis for beating me to the punch in rewriting the code or you're a hero because it's so good haha. Good job, keep it up! :) – Torxed Mar 20 '19 at 09:02
0

Looks like you didn't put pygame. before some of the variables here:

if event.key == K_SPACE: # Does not have pygame prefix
    crazy = 1
if event.key == K_DOWN: # Does not have pygame prefix
    dir = 's'
    y_option -= 1
    hotkey  = 2
if event.key == pygame.K_w: # Does have pygame prefix
    dir = 'w'
    y_option += 1
    hotkey = 1
if event.key == K_LEFT: # Does not have pygame prefix
    dir = 'a'

if event.key == K_RIGHT: # Does not have pygame prefix
    dir = 'd'

Add pygame. to those and it should detect after that. Strange how it didn't pull a NameError exception while it was running however.

Mercury Platinum
  • 1,549
  • 1
  • 15
  • 28
  • 1
    That's not the problem IMHO. OP's code doesn't show the import statement, but they said that there are no errors, so it's safe to assume that `from pygame import *` is used. – sloth Mar 19 '19 at 15:47
  • Good point, but that would make the usage of `pygame.K_w` a bit odd when they could have just used `K_w` like the rest of the if statements. – Mercury Platinum Mar 19 '19 at 15:48
  • 1
    OP expects key-detection in the console. Pygame won't support this. Since it will only trigger on key-down/key-up events in the graphical window. Which hasn't been setup in the code above at all. So there's not even a window to send key events into even if you wanted to. – Torxed Mar 19 '19 at 16:53
  • Ah. That makes sense, I was interpreting it in a different way. – Mercury Platinum Mar 19 '19 at 17:03