General 2d game design book

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

43 Replies - 5889 Views - Last Post: 28 August 2019 - 07:34 AM Rate Topic: -----

#31 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7469
  • View blog
  • Posts: 15,489
  • Joined: 16-October 07

Re: General 2d game design book

Posted 21 August 2019 - 07:45 AM

Heh, my starter project for a language is tic-tac-toe. It hits all the basics and is always amusing. I've also done it multiple ways in the same language. I think I did a C one where the board structures is a 32bit int...

I liked the idea of tetris. I may do one of those. Your's didn't seem responsive enough, I'm afraid. That's actually a hidden challenge in game programming, how to handle events quickly and transparently enough that they don't get in the way of the player hammering on the input.
Was This Post Helpful? 1
  • +
  • -

#32 mrdman   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 21-July 19

Re: General 2d game design book

Posted 21 August 2019 - 08:43 AM

View Postbaavgai, on 21 August 2019 - 07:45 AM, said:

I liked the idea of tetris. I may do one of those. Your's didn't seem responsive enough, I'm afraid. That's actually a hidden challenge in game programming, how to handle events quickly and transparently enough that they don't get in the way of the player hammering on the input.

Yes that's the major flaw out of all of them. Itīs a basic game concept I couldn't get my head around.. I used the fps to control the speed of the falling blocks but that can't be the right way to do it. Fine for the snake game.. but on tetris there must be a better way.

I guess the answer is a high fps, but then to use a timer to control when a block moves down. Maybe on each loop I check to see if 1 second has passed since the block last moved, and if it has, drop it down and update the last moved time. Then inside the high fps loop I'm free to deal with the keystrokes etc however quick I need. Is that how people achieve this behaviour?
Was This Post Helpful? 0
  • +
  • -

#33 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7469
  • View blog
  • Posts: 15,489
  • Joined: 16-October 07

Re: General 2d game design book

Posted 21 August 2019 - 09:25 AM

Yeah, don't mistake your display loop for your entire game loop. Or that clock.tick is remotely useful for anything other than telling the game engine what's going on.

To have things behave as you would like or expect, you'll generally have to look at elapsed time. Or setup another timer for your game stuff.
Was This Post Helpful? 1
  • +
  • -

#34 mrdman   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 21-July 19

Re: General 2d game design book

Posted 22 August 2019 - 01:56 AM

Here's snake reworked without classes... An interesting exercice! The main thing I missed was the access to variables outside of functions. Maybe global variables here would have been ok? I would have liked to have a reset function which would set score, speed, snake and apple.. but without using global variables(evil?) I couldn't see a way of achieving that. So instead I returned a tuple of the variables I wanted to reset and unpacked them like that. Not sure if that's bad practice. It seems dangerous that if I get the order wrong, it breaks.. it would be nice if there was a way for me to grab the correct value via my key but not sure if that's possible.
eg. snake, apple = reset() == apple, snake = reset()

# A version of snake coded without classes #

import pygame, sys, random                  # sys for closing programm.  random for Apple position
from pygame.locals import *                 # for using pygame keywords like QUIT or KEYDOWN

# =========== User changeable data =========== #
GRID_SIZE = 10                      # pixels
GRID_WIDTH, GRID_HEIGHT = 30, 30    # grid cells
STARTING_FPS = 5                    # Starting speed

# =========== CONSTANTS =========== #

# Score bar height bar in pixels
BOTTOMBAR = 50
# Size of playing area in pixels
SCREEN_WIDTH = GRID_WIDTH * GRID_SIZE
SCREEN_HEIGHT = GRID_HEIGHT * GRID_SIZE
# Size of window in pixels
WINDOW_SIZE   = (SCREEN_WIDTH, SCREEN_HEIGHT + BOTTOMBAR)    # Tuple of window size()
# Midpoint of grid in cells
GRID_MID_Y = SCREEN_HEIGHT / 2 / GRID_SIZE  # Mid point on y axis in Grid coordinates
GRID_MID_X = SCREEN_WIDTH / 2 / GRID_SIZE   # Mid point on x axis in Grid coordinates

# Confirm Screen size is divisible by the grid size
assert(SCREEN_WIDTH % GRID_SIZE == 0)
assert(SCREEN_HEIGHT % GRID_SIZE == 0)

DISPLAY = pygame.display.set_mode(WINDOW_SIZE)
BTM_BAR = (0, SCREEN_HEIGHT, SCREEN_WIDTH, BOTTOMBAR)

# =========== COLOURS =========== #
BLACK = (  0,  0,  0)
WHITE = (255,255,255)
GREY =  (155,155,155)
RED   = (255,  0,  0)

# Asset colours #
SNAKE_COLOUR = BLACK
BG_COLOUR = GREY
APPLE_COLOUR = RED
BTM_BAR_COLOR = WHITE
GAME_BG_COLOR = GREY

# =========== KEYWORDS =========== #
x = "x"
y = "y"
UP = "up"
DOWN = "down"
LEFT = "left"
RIGHT = "right"

HEAD = 0
BODY = "body"
DIRECTION_X = "DIRECTION_X"
DIRECTION_Y = "DIRECTION_Y"


# =========== Functions =========== #

def play():
    """ Initialise pygame, reset score, speed, snake and apple and start game loop """

    pygame.init()
    pygame.display.set_caption("Snake")

    reset_screen()
    fps, score, snake, apple = reset()
    display_btm_msg(f"Score: {score}")
    draw_apple(apple)

    fps_clock = pygame.time.Clock()

    ##### Game loop #####
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            # Arrow controls direction, and blocks going directly to direction it came from
            elif event.type == KEYDOWN:
                if event.key == K_LEFT and get_direction(snake) != RIGHT:
                    set_direction(snake, LEFT)
                elif event.key == K_RIGHT and get_direction(snake) != LEFT:
                    set_direction(snake, RIGHT)
                elif event.key == K_UP and get_direction(snake) != DOWN:
                    set_direction(snake, UP)
                elif event.key == K_DOWN and get_direction(snake) != UP:
                    set_direction(snake, DOWN)
                break

        if not move_snake(snake):
            gameover()
            reset_screen()
            fps, score, snake, apple = reset()
            display_btm_msg(f"Score: {score}")
            draw_apple(apple)

        if eating(snake, apple[0], apple[1]):
            score += 1
            apple = rand_apple_pos()
            draw_apple(apple)
            draw_btm_bar()
            display_btm_msg(f"Score: {score}")
            grow(snake)
            fps += 1

        pygame.display.update()
        fps_clock.tick(fps)


def reset():
    """ Return a tuple of fps, score, snake and apple with starting values """
    fps = STARTING_FPS
    score = 0
    snake = reset_snake()
    apple = rand_apple_pos()
    return fps, score, snake, apple


def gameover():
    """ Display game-over message and check for quit, or space bar."""
    display_centre_msg("Press SPACE to play again")
    pygame.display.update()

    while True:
        event = pygame.event.wait()
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == KEYDOWN:
            if event.key == K_SPACE:
                return


def rand_apple_pos():
    """ Return a random cell position within the grid """
    apple = (random.randint(0, GRID_WIDTH - 1),
                 random.randint(0, GRID_HEIGHT - 1))
    return apple


def reset_snake():
    """ Reset the snake BODY, position and direction """
    snake = {BODY: [{x: GRID_MID_X + 0, y: GRID_MID_Y},
                    {x: GRID_MID_X + 1, y: GRID_MID_Y},
                    {x: GRID_MID_X + 2, y: GRID_MID_Y}],
             DIRECTION_X: -1,
             DIRECTION_Y: 0}
    return snake


def draw_snake(snake):
    """ Draw snake on DISPLAY surface """
    for block in snake[BODY]:
        block_position = (block[x] * GRID_SIZE, block[y] * GRID_SIZE, GRID_SIZE, GRID_SIZE)
        pygame.draw.rect(DISPLAY, SNAKE_COLOUR, block_position)


def erase_snake(snake):
    """ Erase snake from DISPLAY surface """
    for block in snake[BODY]:
        block_position = (block[x] * GRID_SIZE, block[y] * GRID_SIZE, GRID_SIZE, GRID_SIZE)
        pygame.draw.rect(DISPLAY, BG_COLOUR, block_position)


def move_snake(snake):
    """ Erase snake from DISPLAY surface, delete last tail position and add new head position in direction
        heading.  Then draw snake in new position.
        If it's outside the screen, or hit its own tail and if so: return False,
                                                            else: return True """
    erase_snake(snake)
    snake[BODY].pop()
    new_head = [{x: snake[BODY][HEAD][x] + snake[DIRECTION_X], y: snake[BODY][HEAD][y] + snake[DIRECTION_Y]}]
    snake[BODY] = new_head + snake[BODY]
    draw_snake(snake)
    if hit_boundary(snake):
        return False
    if hit_body(snake):
        return False
    return True


def set_direction(snake, dir):
    """ Set snake direction to given argument of one of:
        UP, DOWN, RIGHT, LEFT """
    if dir == UP:
        snake[DIRECTION_X] = 0
        snake[DIRECTION_Y] = -1
    elif dir == DOWN:
        snake[DIRECTION_X] = 0
        snake[DIRECTION_Y] = 1
    elif dir == RIGHT:
        snake[DIRECTION_X] = 1
        snake[DIRECTION_Y] = 0
    elif dir == LEFT:
        snake[DIRECTION_X] = -1
        snake[DIRECTION_Y] = 0


def get_direction(snake):
    """ Return the direction the snake is headed """
    if snake[DIRECTION_X] == 1:
        return RIGHT
    elif snake[DIRECTION_X] == -1:
        return  LEFT
    elif snake[DIRECTION_Y] == -1:
        return UP
    elif snake[DIRECTION_Y] == 1:
        return DOWN


def eating(snake, apple_x, apple_y):
    """ Return True if snake head has hit the apple """
    if snake[BODY][HEAD][x] == apple_x and snake[BODY][HEAD][y] == apple_y:
        return True


def grow(snake):
    """ Increase snake BODY size by one """
    new_head = [{x: snake[BODY][HEAD][x] + snake[DIRECTION_X], y: snake[BODY][HEAD][y] + snake[DIRECTION_Y]}]
    snake[BODY] = new_head + snake[BODY]


def hit_body(snake):
    """ Return True if head hits its own BODY, else return False """
    for block in snake[BODY][1:]:
        if block[x] == snake[BODY][HEAD][x] and block[y] == snake[BODY][HEAD][y]:
            return True


def hit_boundary(snake):
    """ Return True if head hits outside the screen """
    if snake[BODY][HEAD][x] < 0 or snake[BODY][HEAD][x] == GRID_WIDTH:
        return True
    if snake[BODY][HEAD][y] < 0 or snake[BODY][HEAD][y] == GRID_HEIGHT:
        return True


def reset_screen():
    """ Call fill_background and draw_btm_bar """
    fill_background()
    draw_btm_bar()


def fill_background():
    """ Fill background with GAME_BG_COLOR """
    DISPLAY.fill(GAME_BG_COLOR)  # Fill window with game background colour


def draw_btm_bar():
    """ Draw bottom bar on DISPLAY surface """
    pygame.draw.rect(DISPLAY, BTM_BAR_COLOR, BTM_BAR)


def draw_apple(pos):
    """ Draw apple to the DISPLAY surface """
    x, y = pos
    block_position = (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE)
    pygame.draw.rect(DISPLAY, APPLE_COLOUR, block_position)


def display_btm_msg(msg):
    """ Display the message(msg) onto the bottom bar """
    fontObj = pygame.font.Font("freesansbold.ttf", min(int(SCREEN_WIDTH / 10), 32))
    score_surface = fontObj.render(msg, True, BLACK)
    score_rect = score_surface.get_rect()
    score_rect.center = (SCREEN_WIDTH / 2, SCREEN_HEIGHT + (BOTTOMBAR / 2))
    DISPLAY.blit(score_surface, score_rect)


def display_centre_msg(msg):
    """ Display the message(msg) onto the centre of screen """
    fontObj = pygame.font.Font("freesansbold.ttf", min(int(SCREEN_WIDTH / 14), 25))
    new_game_surface = fontObj.render(msg, True, BLACK)
    new_game_rect = new_game_surface.get_rect()
    new_game_rect.center = (SCREEN_WIDTH / 2,SCREEN_HEIGHT /2)
    DISPLAY.blit(new_game_surface, new_game_rect)


if __name__ == "__main__":
    play()



Was This Post Helpful? 0
  • +
  • -

#35 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7469
  • View blog
  • Posts: 15,489
  • Joined: 16-October 07

Re: General 2d game design book

Posted 22 August 2019 - 04:55 AM

Hmm... I'd argue you still have one global, DISPLAY. I removed it.

You also should never use sys.exit: it's a sign you've failed game loop logic.

I also happened by your hit_boundary and it made me twitch, so I fiddled with it. In fact, it has a bug that only the truthy nature of None was saving you from: always return a value if you've promised a value, even if it is just an explicit None.

For globals, that's the idea of game state. A bundle of things that represent all the moving parts of a game. It's some cases, it is literally the contents of a save file.

However, for the main surface of a game (screen, display, etc), that should be initialized in main and passed about, not initialized in the global context. This also has the benefit that if you, at some point, decide to draw on a different surface for some game element, it's a drop in solution.

My messing with your code. By no means exhaustive:
import pygame
# no, never import sys
import random                  # sys for closing programm.  random for Apple position
# for using pygame keywords like QUIT or KEYDOWN
from pygame.locals import *

# =========== User changeable data =========== #
GRID_SIZE = 10                      # pixels
GRID_WIDTH, GRID_HEIGHT = 30, 30    # grid cells
STARTING_FPS = 5                    # Starting speed

# =========== CONSTANTS =========== #

# Score bar height bar in pixels
BOTTOMBAR = 50
# Size of playing area in pixels
SCREEN_WIDTH = GRID_WIDTH * GRID_SIZE
SCREEN_HEIGHT = GRID_HEIGHT * GRID_SIZE
# Size of window in pixels
WINDOW_SIZE = (SCREEN_WIDTH, SCREEN_HEIGHT +
               BOTTOMBAR)    # Tuple of window size()
# Midpoint of grid in cells
# Mid point on y axis in Grid coordinates
GRID_MID_Y = SCREEN_HEIGHT / 2 / GRID_SIZE
# Mid point on x axis in Grid coordinates
GRID_MID_X = SCREEN_WIDTH / 2 / GRID_SIZE

# Confirm Screen size is divisible by the grid size
assert(SCREEN_WIDTH % GRID_SIZE == 0)
assert(SCREEN_HEIGHT % GRID_SIZE == 0)

# DISPLAY = pygame.display.set_mode(WINDOW_SIZE)
BTM_BAR = (0, SCREEN_HEIGHT, SCREEN_WIDTH, BOTTOMBAR)

# =========== COLOURS =========== #
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREY = (155, 155, 155)
RED = (255, 0, 0)

# Asset colours #
SNAKE_COLOUR = BLACK
BG_COLOUR = GREY
APPLE_COLOUR = RED
BTM_BAR_COLOR = WHITE
GAME_BG_COLOR = GREY

# =========== KEYWORDS =========== #
x = "x"
y = "y"
UP = "up"
DOWN = "down"
LEFT = "left"
RIGHT = "right"

HEAD = 0
BODY = "body"
DIRECTION_X = "DIRECTION_X"
DIRECTION_Y = "DIRECTION_Y"


# =========== Functions =========== #


def reset():
    """ Return a tuple of fps, score, snake and apple with starting values """
    fps = STARTING_FPS
    score = 0
    snake = reset_snake()
    apple = rand_apple_pos()
    return fps, score, snake, apple


def gameover(screen):
    """ Display game-over message and check for quit, or space bar."""
    display_centre_msg(screen, "Press SPACE to play again")
    pygame.display.update()

    while True:
        event = pygame.event.wait()
        if event.type == QUIT:
            # no pygame.quit()
            # never sys.exit()
            return True
        elif event.type == KEYDOWN:
            if event.key == K_SPACE:
                return False


def rand_apple_pos():
    """ Return a random cell position within the grid """
    apple = (random.randint(0, GRID_WIDTH - 1),
             random.randint(0, GRID_HEIGHT - 1))
    return apple


def reset_snake():
    """ Reset the snake BODY, position and direction """
    snake = {BODY: [{x: GRID_MID_X + 0, y: GRID_MID_Y},
                    {x: GRID_MID_X + 1, y: GRID_MID_Y},
                    {x: GRID_MID_X + 2, y: GRID_MID_Y}],
             DIRECTION_X: -1,
             DIRECTION_Y: 0}
    return snake


def draw_snake(screen, snake):
    """ Draw snake on DISPLAY surface """
    for block in snake[BODY]:
        block_position = (block[x] * GRID_SIZE, block[y]
                          * GRID_SIZE, GRID_SIZE, GRID_SIZE)
        pygame.draw.rect(screen, SNAKE_COLOUR, block_position)


def erase_snake(screen, snake):
    """ Erase snake from DISPLAY surface """
    for block in snake[BODY]:
        block_position = (block[x] * GRID_SIZE, block[y]
                          * GRID_SIZE, GRID_SIZE, GRID_SIZE)
        pygame.draw.rect(screen, BG_COLOUR, block_position)


def move_snake(screen, snake):
    """ Erase snake from DISPLAY surface, delete last tail position and add new head position in direction
        heading.  Then draw snake in new position.
        If it's outside the screen, or hit its own tail and if so: return False,
                                                            else: return True """
    erase_snake(screen, snake)
    snake[BODY].pop()
    new_head = [{x: snake[BODY][HEAD][x] + snake[DIRECTION_X],
                 y: snake[BODY][HEAD][y] + snake[DIRECTION_Y]}]
    snake[BODY] = new_head + snake[BODY]
    draw_snake(screen, snake)
    if hit_boundary(snake):
        return False
    if hit_body(snake):
        return False
    return True


def set_direction(snake, dir):
    """ Set snake direction to given argument of one of:
        UP, DOWN, RIGHT, LEFT """
    if dir == UP:
        snake[DIRECTION_X] = 0
        snake[DIRECTION_Y] = -1
    elif dir == DOWN:
        snake[DIRECTION_X] = 0
        snake[DIRECTION_Y] = 1
    elif dir == RIGHT:
        snake[DIRECTION_X] = 1
        snake[DIRECTION_Y] = 0
    elif dir == LEFT:
        snake[DIRECTION_X] = -1
        snake[DIRECTION_Y] = 0


def get_direction(snake):
    """ Return the direction the snake is headed """
    if snake[DIRECTION_X] == 1:
        return RIGHT
    elif snake[DIRECTION_X] == -1:
        return LEFT
    elif snake[DIRECTION_Y] == -1:
        return UP
    elif snake[DIRECTION_Y] == 1:
        return DOWN


def eating(snake, apple_x, apple_y):
    """ Return True if snake head has hit the apple """
    if snake[BODY][HEAD][x] == apple_x and snake[BODY][HEAD][y] == apple_y:
        return True


def grow(snake):
    """ Increase snake BODY size by one """
    new_head = [{x: snake[BODY][HEAD][x] + snake[DIRECTION_X],
                 y: snake[BODY][HEAD][y] + snake[DIRECTION_Y]}]
    snake[BODY] = new_head + snake[BODY]


def hit_body(snake):
    """ Return True if head hits its own BODY, else return False """
    for block in snake[BODY][1:]:
        if block[x] == snake[BODY][HEAD][x] and block[y] == snake[BODY][HEAD][y]:
            return True


def hit_boundary(snake):
    """ Return True if head hits outside the screen """
    # if snake[BODY][HEAD][x] < 0 or snake[BODY][HEAD][x] == GRID_WIDTH:
    #     return True
    # if snake[BODY][HEAD][y] < 0 or snake[BODY][HEAD][y] == GRID_HEIGHT:
    #     return True
    # head = snake[BODY][HEAD]
    # return head[x] < 0 or head['x'] == GRID_WIDTH or head[y] < 0 or head[y] == GRID_HEIGHT
    x, y = (snake[BODY][HEAD][k] for k in ('x', 'y'))
    return x < 0 or x == GRID_WIDTH or y < 0 or y == GRID_HEIGHT


def reset_screen(screen):
    """ Call fill_background and draw_btm_bar """
    fill_background(screen)
    draw_btm_bar(screen)


def fill_background(screen):
    """ Fill background with GAME_BG_COLOR """
    screen.fill(GAME_BG_COLOR)  # Fill window with game background colour


def draw_btm_bar(screen):
    """ Draw bottom bar on DISPLAY surface """
    pygame.draw.rect(screen, BTM_BAR_COLOR, BTM_BAR)


def draw_apple(screen, pos):
    """ Draw apple to the DISPLAY surface """
    x, y = pos
    block_position = (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE)
    pygame.draw.rect(screen, APPLE_COLOUR, block_position)


def display_btm_msg(screen, msg):
    """ Display the message(msg) onto the bottom bar """
    fontObj = pygame.font.Font(
        "freesansbold.ttf", min(int(SCREEN_WIDTH / 10), 32))
    score_surface = fontObj.render(msg, True, BLACK)
    score_rect = score_surface.get_rect()
    score_rect.center = (SCREEN_WIDTH / 2, SCREEN_HEIGHT + (BOTTOMBAR / 2))
    screen.blit(score_surface, score_rect)


def display_centre_msg(screen, msg):
    """ Display the message(msg) onto the centre of screen """
    fontObj = pygame.font.Font(
        "freesansbold.ttf", min(int(SCREEN_WIDTH / 14), 25))
    new_game_surface = fontObj.render(msg, True, BLACK)
    new_game_rect = new_game_surface.get_rect()
    new_game_rect.center = (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)
    screen.blit(new_game_surface, new_game_rect)


def play():
    """ Initialise pygame, reset score, speed, snake and apple and start game loop """

    pygame.init()
    screen = pygame.display.set_mode(WINDOW_SIZE)
    pygame.display.set_caption("Snake")

    reset_screen(screen)
    fps, score, snake, apple = reset()
    display_btm_msg(screen, f"Score: {score}")
    draw_apple(screen, apple)

    fps_clock = pygame.time.Clock()

    ##### Game loop #####
    done = False
    while not done:
        for event in pygame.event.get():
            if event.type == QUIT:
                done = True
                break
                # not here pygame.quit()
                # never sys.exit()

            # Arrow controls direction, and blocks going directly to direction it came from
            elif event.type == KEYDOWN:
                if event.key == K_LEFT and get_direction(snake) != RIGHT:
                    set_direction(snake, LEFT)
                elif event.key == K_RIGHT and get_direction(snake) != LEFT:
                    set_direction(snake, RIGHT)
                elif event.key == K_UP and get_direction(snake) != DOWN:
                    set_direction(snake, UP)
                elif event.key == K_DOWN and get_direction(snake) != UP:
                    set_direction(snake, DOWN)
                break  # I don't understand this break
        if done:
            break
        if not move_snake(screen, snake):
            done = gameover(screen)
            if done:
                break
            reset_screen(screen)
            fps, score, snake, apple = reset()
            display_btm_msg(screen, f"Score: {score}")
            draw_apple(screen, apple)

        if eating(snake, apple[0], apple[1]):
            score += 1
            apple = rand_apple_pos()
            draw_apple(screen, apple)
            draw_btm_bar(screen)
            display_btm_msg(screen, f"Score: {score}")
            grow(snake)
            fps += 1

        pygame.display.update()
        fps_clock.tick(fps)
    pygame.quit()

if __name__ == "__main__":
    play()


Was This Post Helpful? 0
  • +
  • -

#36 mrdman   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 21-July 19

Re: General 2d game design book

Posted 22 August 2019 - 06:56 AM

That's amazing.. thanks!

re: hit_boundary: Ah yes.. I recently came across that pattern of returning the evaluation directly and I like it. Need to practice returning evaluations directly. I always default to separating the expression from the return for some reason.

That break after the keydowns is how I am stopping a quick "left, right" from making the snake move into itself. However, there must be a better way of doing this I'd imagine. Maybe I don't need to be getting events via the event.get but maybe event.wait like my gameover function.

Passing screen around makes sense yes. I guess I need to go and look at more people's code to get an idea of correct ways to do things as I had considered using that way of passing the surface into functions, rather than the global DISPLAY but I just had no way to know which way was the better way.
Was This Post Helpful? 0
  • +
  • -

#37 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7469
  • View blog
  • Posts: 15,489
  • Joined: 16-October 07

Re: General 2d game design book

Posted 22 August 2019 - 09:01 AM

Of course, there is no "correct way." Programming is as much organizing as actual problem solving. Anything I'd offer is with the parenthetical "this looks like a good way to do it right now." It's really much easier to spot certain "omfg, don't do that" instances. The recursion thing was one of those.

Every "good in most cases" rule has an exception. I go on runs of playing with different paradigms, only to come up later and say: well, that's worth keeping, that might be over doing it, wtf was I thinking with that.
Was This Post Helpful? 0
  • +
  • -

#38 mrdman   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 21-July 19

Re: General 2d game design book

Posted 23 August 2019 - 03:49 AM

Ah ok yes that makes sense. So it's more about getting used to spotting bad implementations to avoid. I guess in the mean time I should keep experimenting and forcing myself to code things in different ways to get that experience. I think the next task I'll do is rework my tetris so that it is more responsive, and doesn't have the recursive start and pointless main class etc.
Was This Post Helpful? 0
  • +
  • -

#39 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7469
  • View blog
  • Posts: 15,489
  • Joined: 16-October 07

Re: General 2d game design book

Posted 23 August 2019 - 04:49 AM

So, I started plinking on the tetris thing myself. Most games I program are more programming exercises than anything else. Not so, Tetris. I love tetris and it was possibly my greatest time sink in college. I played this version:

Attached Image

My current work is found here: https://github.com/Baavgai/bablok

And, at the moment, looks like this:
Attached Image

I'm having a lot of fun with it. Mostly because, well, I like to play it. I need to add a score and levels.

Alas, the commits don't represent true history. I tried to tease out history from the larger repo it started in, but it came with too much cruft and it was easier to just start fresh.

I liked that tetris has that break up the screen into blocks thing going on. I'm considering moving out of that paradigm for block movement, but this seems truer to than ancient PC game I'm fond of.

If you actually peruse the source, you will note I used globals! This was a function of an MVC experiment with the design and a desire to cache some objects. The display might be pushed into a true object, but the block images aren't offending me just yet and may live where there are.
Was This Post Helpful? 1
  • +
  • -

#40 NeoTifa   User is offline

  • NeoTifa Codebreaker, the Scourge of Devtester
  • member icon





Reputation: 4547
  • View blog
  • Posts: 19,185
  • Joined: 24-September 08

Re: General 2d game design book

Posted 23 August 2019 - 08:31 AM

next you should make dr mario :P
Was This Post Helpful? 0
  • +
  • -

#41 mrdman   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 21-July 19

Re: General 2d game design book

Posted 23 August 2019 - 09:47 AM

That's amazing! Great work and glad to have had a small part in inspiring you!
I won't look at your code for now.. as I would like to solve the game play aspect of my tetris first (I always find struggling through a problem myself helps me remember the solution later down the road)
I love the way yours looks.. it's amazing how decent graphics makes the project that much more playable! The first time I put the simple black outline around each individual square on mine suddenly made it so much more fun than without that! Why?!

I used to love tetris too. As you can imagine my three favourite 2d games along the years were snake, tetris and chess! haha
Was This Post Helpful? 0
  • +
  • -

#42 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7469
  • View blog
  • Posts: 15,489
  • Joined: 16-October 07

Re: General 2d game design book

Posted 23 August 2019 - 10:25 AM

View Postmrdman, on 23 August 2019 - 11:47 AM, said:

suddenly made it so much more fun than without that! Why?!

Heh, totally agree. Just a little spiffing up makes all the difference.

So, I googled tetris and found this screenshot:
Attached Image

Not only did I like the look, I liked the simplicity of implementation. Once you've drawn one block, you're good to go. In truth, I did a screen sampling to figure out the colors I wanted from that.

So, the current version: :P
Attached Image
Was This Post Helpful? 0
  • +
  • -

#43 mrdman   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 21-July 19

Re: General 2d game design book

Posted 24 August 2019 - 12:59 AM

That looks so good! Congrats!! It's amazing to think that we can code one of the most popular games worldwide ever, in a few evenings.. Now if only we could do that before anyone else did it first! :P
Was This Post Helpful? 0
  • +
  • -

#44 mrdman   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 21-July 19

Re: General 2d game design book

Posted 28 August 2019 - 07:34 AM

Finally got some time to make mine playable and fix some of the bad design practices I had done.. so now it's responsive to play. So I can now look at your code without feeling like I cheated!
Such good code! That's exactly what I was talking about when I said other people's code looks like short little functions and mine looks like a long novel! I'll need some time to take it all in but going to enjoy working through it in more detail. I've never coded in MVC so only have a passing knowledge of what is exactly is so that's something I will have to look into more too.
Was This Post Helpful? 1
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3