Giter Club home page Giter Club logo

calcium's Introduction

Calcium

example-01-running

Calcium is a python 3 library to build games (or interactive applications) in terminal emulators. It works by creating a "Calcium Screen" that represents a virtual screen filled with 0s and 1s and plotting this virtual screen to the terminal emulator.

Learning the basics

Main Concepts

Every calcium application must inherits from core.TerminalApplication and override the function update. The update is the function that is called in every single frame. So let's look how we can plot a single pixel in the screen:

from calcium import core

class HelloWorldApp(core.TerminalApplication):
    def update(self):
        self.clear()
        self.set_pixel(2, 2, 1)
        self.draw()


if __name__ == "__main__":
    HelloWorldApp.run()

example-01-running

The TerminalApplication has a property called screen. It represents a virtual screen and all drawing that we can do is made in this virtual screen. On every frame we can draw on this virtual screen and then plot this virtual screen in the terminal. The clear method clears the virtual screen and clears the terminal emulator screen. The set_pixel call draws a pixel in the (2, 2) coordinate, in the virtual screen, and finally, the draw method plot the virtual screen to the terminal emulator screen.

The virtual screen, in the most cases, don't need to be accessed directly, but you can do it if you want. Just do:

# setting the upper left corner to 1 (filled)
def update(self):
    ...
    self.screen.lines[0][0] = 1
    ...

Sprites and Filters

A sprite is a collection of pixels arranged around a point/coordinate. The point/coordinate we can call "origin" or "position" of the sprite. We use functions called "filters" to determine the pixel data binded to the sprite. The pixels data returned from filters must be in the format x, y, (1 or 0). So, if we a have a sprite in the position (10, 10) and it have only one white pixel, located in the same sprite's origin point, the pixel data returned from one filter must be: [0, 0, 1], if the sprite have two pixels, one in the origin point and other next to it, in your right side, the pixel data returned by the filter will be: [0, 0, 1, 1, 0, 1]. Every time we move the sprite in the virtual screen the points will be moved together. Let's see an example of an sprite with three pixels, one black pixel in between two white pixels:

from calcium import core

class MySpritePixelsFilter(core.BaseFilter):
    def get(self, pixels):
        return [
            0, 0, 1,
            1, 0, 0,
            2, 0, 1,
        ]

class MyApp(core.TerminalApplication):
    def __init__(self):
        super().__init__()
        self.sprite = core.Sprite(filters=[
            MySpritePixelsFilter()
        ])

    def update(self):
        self.clear()
        self.plot_sprite(self.sprite)
        self.draw()

MyApp().run()

example-02-running

You probably noted the used of plot_sprite method. It do just what are thinking! It draw the points returned by all the filters of the sprite in the virtual screen.

Why we use filters to set the sprite's pixels? Because we can arrange filters one next to other to create a chain of effects! This is a try to make a more flexible sprite effects design. For example, we can create a filter that creates randomically pixels data, and next to it, append another filter that takes the pixels returned by the last filter and proccess it, making a border around the pixels, or inverting the colors of last filters, or making the pixels show/hide periodically, making it flash...many possibilities!

This is why, in the example above, the method get of our MySpritePixelsFilter receive a pixels argument. This argument stores the pixels returned by the last filter.

So let's try some default filter to you understand the power of them:

from calcium import core
from calcium import filters
class MyApp(core.TerminalApplication):
    def __init__(self):
        super().__init__()
        self.sprite = core.Sprite(filters=[
            filters.RawImageFilter(image_path="./lenna.png"),
            filters.InvertFilter(),
        ])

    def update(self):
        self.clear()
        self.plot_sprite(self.sprite)
        self.draw()

MyApp().run()

Above you can see two filters working together. The first takes one image, converts to black/white and the next one takes the pixels returned by the last filter and invert its colors.

example-03-running

Note that the order of filters is very important, if we invert the filters order in the example above, making the invert filters first, the image will be shown without any effect. This will happen because the invert filter will receive none pixels (because before it doesn't exist any filter) and than we will include an filter that just ignores the last pixel data. This one thing to pay attention when working with filters, you will need to know if it uses the last pixel data or just ignores it. Below we have the list of default filters available:

filters.InvertFilter

Invert the colors of last pixels

filters.BoundsFilter

Do nothing with the pixels. Just receive them and return them back. This filter is used to calculate the width/height os sprite and create dinamic properties in the sprite. This is used basically for alignment or physics.

filters.RawImageFilter

Ignores the last pixels, so you want to use this filter in the beginning of filters list. It receives a PIL.Image instance or a file path with the image. Note that the image will not be resized when using this filter, so, use images already resized.

filters.SpriteSheetFilter

Ignores the last pixels, so you want to use this filter in the beginning of filters list. It receives a list of PIL.Image instances and switch them in the time making animations.

filters.PlatformPhysicsFilter

Do nothing with the pixels. Just receive them and return them back. This filter is used to make objects interacts with others. This is meant to a very basic platform games.

Sprite observable properties

TODO

Timers

TODO

Scenes

TODO

Sounds

TODO

Animation

TODO

How I can help

  • create cool filters
  • do improvements in the CI (because is not set yet :p )
  • CREATE GAMES!

Games powered by Calcium

  • include a game here please...

calcium's People

Contributors

capostudios avatar cptx032 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

calcium's Issues

create a "Scene" class and bind events to it

Today the events are binded to core.GenericWindow, that is, to the Window/terminal it self.
This is not much practical if we have many game states.
So the idea is that you can bind the events to different scenes, so when you switch the scene the binds are "updated".

"Automatic binds" like "ESC" must be made ate scene level

The new schema (in json, just to have an idea) could be:

window = {
    "scenes": [
        {
                "name": "scene_name",
                "binds": [..., ...]
        }
    ],
    "actual_scene": "scene_name"
}

center screen in terminal

off in screen when the screen have a size less than terminal

create a example "pixel flappy" of 32x32 pixels centering in the screen

separate sprite class

Today a sprite already has frame animation support, but not all sprites will have animation, so the idea is to create a "flat" sprite, without animation.
So will exists a AnimatedSprite to suport animation. Both classes must be "effectable", like screen class today: I must call MyEffect.process(mysprite) and the sprite will be affected just for that frame.

load from image options

actually the brighter pixels are converted in filled characters, but if you draw things in black in a white background will want that black pixels be converted to filled characters. Just a flag would fix this

Error in setup.py

Hi,
I was interessed using your library but when I try to pip install it, I got this error :

Complete output from command python setup.py egg_info:
    error in calcium setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers; Invalid requirement, parse error at "'=5.0.0'"

create a "calcium apps browser"

search applications made in calcium in github and download them and play them without manually clone or something like that

maybe search projects that are using a "calcium-app" tag? (is possible search projects by tag in github api?)

calcium.arcade ?

Hello,

the example platform_system.py use a module called arcade. This module does not exists (platform_system.py raise an ImportError).

What about this module ? Is it a an aborted feature ? Or not yet implemented ?

By the way, for some reason i can't run pong.py and windfarm.py

Otherwise the tool looks great. Thank you for all this work !!

clock functions

create functions in scene class:

  • schedule_interval
  • schedule_once

Effects

  • when active the screen flashes in a specific frequency
  • border screen - to put border in screen
  • reflexion effect (vertical/horizontal)

show sprites in true terminal colors

now will be used only two ascii chars: filled, half-filled. We can set the two colors different by setting diferent bg and fg colors to characters (\033[38;2;r;g;bm -> fg, \033[48;2;r;g;b - >bg)
https://en.wikipedia.org/wiki/ANSI_escape_code

Create a Sprite filters

sprite = Sprite(x, y, animations={'running': []})
sprite.dark(level=1)
sprite.light(level=1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.