Complete Roguelike Tutorial, using python3+pysdl2, part 1 code

From RogueBasin
Revision as of 22:15, 3 January 2017 by Lukems-br (talk | contribs) (time.py)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This is part of a series of tutorials; the main page can be found here.

The tutorial uses libtcod version 1.6.0 and above.

If you choose to use 1.5.1, you can find the old version here.
If you choose to use 1.5.0, you can find the old version here.


util/time.py

"""Modified, pure Python implementation of PyGameSDL2's pygame_time."""

"""
    Original source code available at:
        github.com/
            renpy/pygame_sdl2/blob/master/src/pygame_sdl2/pygame_time.pyx

    Altered source plain mark:
    --------------------------------------------------------------------------
               _ _                    _                                  _
         /\   | | |                  | |                                | |
        /  \  | | |_ ___ _ __ ___  __| |    ___  ___  _   _ _ __ ___ ___| |
       / /\ \ | | __/ _ \ '__/ _ \/ _` |   / __|/ _ \| | | | '__/ __/ _ \ |
      / ____ \| | ||  __/ | |  __/ (_| |   \__ \ (_) | |_| | | | (_|  __/_|
     /_/    \_\_|\__\___|_|  \___|\__,_|   |___/\___/ \__,_|_|  \___\___(_)

    --------------------------------------------------------------------------

    PygameSDL2 Notice / zlib License:
    --------------------------------------------------------------------------
    # Original work:
    #    Copyright 2014 Tom Rothamel <tom@rothamel.us>
    #    Copyright 2014 Patrick Dawson <pat@dw.is>
    # Modified work:
    #    Copyright 2017 Lucas Siqueira <lucas.morais.siqueira@gmail.com>
    #
    # This software is provided 'as-is', without any express or implied
    # warranty.  In no event will the authors be held liable for any damages
    # arising from the use of this software.
    #
    # Permission is granted to anyone to use this software for any purpose,
    # including commercial applications, and to alter it and redistribute it
    # freely, subject to the following restrictions:
    #
    # 1. The origin of this software must not be misrepresented; you must not
    #    claim that you wrote the original software. If you use this software
    #    in a product, an acknowledgment in the product documentation would be
    #    appreciated but is not required.
    # 2. Altered source versions must be plainly marked as such, and must not
    #    be misrepresented as being the original software.
    # 3. This notice may not be removed or altered from any source
    #    distribution.
    --------------------------------------------------------------------------
"""


import math
from sdl2 import SDL_Delay, SDL_GetTicks


__all__ = ('Clock', 'wait', 'get_time', 'get_delta')


def get_delta(t0):
    """Get the time elapsed since the passed time."""
    return get_time - t0


def get_time():
    """Get the current time from SDL clock."""
    return SDL_GetTicks()


def wait(milliseconds):
    """Pause the program for an amount of time.

    Will pause for a given number of milliseconds. This function sleeps the
    process to share the processor with other programs. A program that waits
    for even a few milliseconds will consume very little processor time.

    Usage:
        wait(milliseconds)

    Returns:
        int (the actual number of milliseconds used)
    """
    start = SDL_GetTicks()
    SDL_Delay(int(milliseconds))
    return SDL_GetTicks() - start


class Clock:
    """Clock is used track and control the framerate of a game.

    The clock can be used to limit the framerate of a game, as well as track
    the time used per frame.

    Usage:
        clock = time.Clock()
    """

    def __init__(self):
        """Initialization."""
        self.last = SDL_GetTicks()
        self.last_frames = []
        self.frametime = 0
        self.raw_frametime = 0

    def tick(self, framerate=0):
        """Update the Clock.

        This method should be called once per frame. It will compute how many
        milliseconds have passed since the previous call.

        If you pass the optional framerate argument the function will delay
        to keep the game running slower than the given ticks per second. This
        can be used to help limit the runtime speed of a game. By calling
        clock.tick(40) once per frame, the program will never run at more
        than 40 frames per second.

        Usage:
            tick(framerate=0)

        Returns:
            float (milliseconds)
        """
        now = SDL_GetTicks()
        self.raw_frametime = now - self.last
        while len(self.last_frames) > 9:
            self.last_frames.pop(0)
        if framerate == 0:
            self.last = now
            self.last_frames.append(self.raw_frametime)
            return self.raw_frametime
        frame_duration = 1.0 / framerate * 1000
        if self.raw_frametime < frame_duration:
            wait(frame_duration - self.raw_frametime)
        now = SDL_GetTicks()
        self.frametime = now - self.last
        self.last = now
        self.last_frames.append(self.frametime)
        return self.frametime

    def get_time(self):
        """Time used in the previous tick.

        Returns the parameter passed to the last call to Clock.tick().

        Usage:
            clock.get_time()

        Returns:
            int (milliseconds)
        """
        return self.frametime

    def get_rawtime(self):
        """Actual time used in the previous tick.

        Similar to Clock.get_time(), but this does not include any time used
        while clock.tick() was delaying to limit the framerate.

        Usage:
            clock.get_rawtime()

        Returns:
            int (milliseconds)
        """
        return self.raw_frametime

    def get_fps(self):
        """Compute the clock framerate.

        Compute your game’s framerate (in frames per second). It is computed
        by averaging the last ten calls to Clock.tick().

        Usage:
            get_fps()

        Returns:
            float
        """
        total_time = sum(self.last_frames)
        average_time = total_time / 1000.0 / len(self.last_frames)
        average_fps = 1.0 / average_time
        return 0 if math.isnan(average_fps) else average_fps


Showing the @ on screen

import libtcodpy as libtcod

#actual size of the window
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50

LIMIT_FPS = 20  #20 frames-per-second maximum


libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod tutorial', False)

libtcod.sys_set_fps(LIMIT_FPS)

while not libtcod.console_is_window_closed():
    
    libtcod.console_set_default_foreground(0, libtcod.white)
    
    libtcod.console_put_char(0, 1, 1, '@', libtcod.BKGND_NONE)
    
    libtcod.console_flush()


Moving around

import libtcodpy as libtcod

#actual size of the window
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50

LIMIT_FPS = 20  #20 frames-per-second maximum


def handle_keys():
    global playerx, playery
    
    #key = libtcod.console_check_for_keypress()  #real-time
    key = libtcod.console_wait_for_keypress(True)  #turn-based
    
    if key.vk == libtcod.KEY_ENTER and key.lalt:
        #Alt+Enter: toggle fullscreen
        libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
        
    elif key.vk == libtcod.KEY_ESCAPE:
        return True  #exit game
    
    #movement keys
    if libtcod.console_is_key_pressed(libtcod.KEY_UP):
        playery -= 1
        
    elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN):
        playery += 1
        
    elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT):
        playerx -= 1
        
    elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT):
        playerx += 1


#############################################
# Initialization & Main Loop
#############################################

libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod tutorial', False)
libtcod.sys_set_fps(LIMIT_FPS)

playerx = SCREEN_WIDTH/2
playery = SCREEN_HEIGHT/2

while not libtcod.console_is_window_closed():
    
    libtcod.console_set_default_foreground(0, libtcod.white)
    libtcod.console_put_char(0, playerx, playery, '@', libtcod.BKGND_NONE)
    
    libtcod.console_flush()
    
    libtcod.console_put_char(0, playerx, playery, ' ', libtcod.BKGND_NONE)
    
    #handle keys and exit game if needed
    exit = handle_keys()
    if exit:
        break