Skip to content

Python-Ninja-Hebi/wonderworld

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wonderworld - Data-oriented Python Game Engine







  • Game Engine implemented on Database Engine (in memory with pandas)
  • world is a database
  • archetype is a table
  • entity is a row(id)
  • componenten is one column
  • system is a function
  • query is a database query
  • Now with pydantic https://docs.pydantic.dev/latest/

I have long wanted to program games in Pygame using the Entity Component System (ECS) game design pattern. Once when I looked at the Bevy game framework in Rust, I was hooked. I wanted something like that in Python too. Since I couldn't find such a framework anywhere, I started developing a Python ECS framework myself - wonderworld

Entity Component System ECS

The data-oriented programming (DOP) approach tries to strictly separate data and program from each other.

One way to do this is with the Entity Component System (ECS) design pattern.

A component in the ECS design pattern contains only data.

Examples:

  • Transform(x,y) - TransformComponent
  • Speed (x,y) - SpeedComponent
  • Sprite(image) - ImageComponent

A component does not contain any processing logic.

An entity is a game object, such as the knight. It consists of any number of components and does not itself contain any data or program logic. A unique ID linked to the components via an internal data structure is sufficient for the implementation of an entity.

A system contains the complete processing logic, but no own data. A game can consist of any number of systems. A system reads components and transforms their current state into another.

For example, the Movement system retrieves all speed components (SpeedComponents) and transform components (PositionComponent) in order to calculate the new position from them.







Bevy







https://bevyengine.org

pygame







https://www.pygame.org

Example first.py









from wonderworld import * PADDLE_VELOCITY: float = 180.0 class Paddle(Component): pass def setup(): commands = get_commands() assets = get_resource(Assets) # asset_server = get_resource(AssetServer) # image_handle = asset_server.load("box.png"); image_handle = assets.add(create_image(color=pygame.Color('white'), size=Vector2(10.0, 100.0))) # camera commands.spawn(Camera2dBundle(camera=Camera(), transform=Transform(translation=Vector2(0,0), rotation=0, scale=Vector2(0, 0)))) # paddle commands.spawn(SpriteBundle(sprite=Sprite(image=image_handle), transform=Transform(translation=Vector2(100, 100), rotation=0, scale=Vector2(0, 0)), visibility=Visibility(visible=True))) \ .insert(Paddle()) def input(): time = get_resource(Time) keyboard_input = get_resource(Keyboard) for transform, in Query(Transform, With(Paddle)): paddle_move = time.delta_seconds * PADDLE_VELOCITY if keyboard_input.pressed(K_UP): transform.translation.y = transform.translation.y - paddle_move if keyboard_input.pressed(K_DOWN): transform.translation.y = transform.translation.y + paddle_move if __name__ == "__main__": App().insert_resource(ClearColor(color=pygame.Color('black'))) \ .add_plugins(DefaultPlugins()) \ .add_startup_system(setup) \ .add_system(input) \ .run()
pygame 2.1.2 (SDL 2.0.18, Python 3.9.16) Hello from the pygame community. https://www.pygame.org/contribute.html 

Example ping.py









from wonderworld import * HEIGHT = 600 WIDTH = 800 PADDLE_WIDTH: float = 10.0 PADDLE_HEIGHT: float = 100.0 PADDLE_VELOCITY: float = 180.0 PADDLE_MAX_MOVE: float = HEIGHT - PADDLE_HEIGHT PADDLE_MIN_MOVE: float = 0 BALL_WIDTH: float = 10.0 BALL_VELOCITY: Vector2 = Vector2(160.0, 160.0) LINE_WIDTH: float = 2.0; class Score(Resource): left: int right: int class Ball(Component): pass class Paddle(Component): up_key: int down_key: int class Velocity(Component): value: Vector2 class LeftText(Component): pass class RightText(Component): pass def setup(): commands = get_commands() assets = get_resource(Assets) # camera commands.spawn(Camera2dBundle(camera=Camera(), transform=Transform())) # ball ball_handle = assets.add(create_image(color=pygame.Color('white'), size=Vector2(BALL_WIDTH, BALL_WIDTH))) commands.spawn(SpriteBundle(sprite=Sprite(image=ball_handle), transform=Transform(translation=Vector2(100, 100)), visibility=Visibility(visible=True))) \ .insert(Velocity(value=BALL_VELOCITY.copy())) \ .insert(Ball()) # line line_handle = assets.add(create_image(color=pygame.Color('white'), size=Vector2(LINE_WIDTH, HEIGHT))) commands.spawn(SpriteBundle(sprite=Sprite(image=line_handle), transform=Transform(translation=Vector2(WIDTH / 2, 0)), visibility=Visibility(visible=True))) # paddle_left left_handle = assets.add(create_image(color=pygame.Color('white'), size=Vector2(PADDLE_WIDTH, PADDLE_HEIGHT))) commands.spawn(SpriteBundle(sprite=Sprite(image=left_handle), transform=Transform(translation=Vector2(0.0, HEIGHT / 2.0 - PADDLE_HEIGHT / 2)), visibility=Visibility(visible=True))) \ .insert(Paddle(up_key=K_w, down_key=K_a)) # paddle_right right_handle = assets.add(create_image(color=pygame.Color('white'), size=Vector2(PADDLE_WIDTH, PADDLE_HEIGHT))) commands.spawn(SpriteBundle(sprite=Sprite(image=right_handle), transform=Transform(translation=Vector2(WIDTH - PADDLE_WIDTH, HEIGHT / 2.0 - PADDLE_HEIGHT / 2)), visibility=Visibility(visible=True))) \ .insert(Paddle(up_key=K_UP, down_key=K_DOWN)) # score asset_server = get_resource(AssetServer) font_size = 64 commands.spawn(Text2dBundle( text = Text(text="0", font = asset_server.load("fonts/FiraSans-Bold.ttf",AssetType.FONT,size=font_size), font_size = font_size, color = Color('white') ), transform = Transform(translation=Vector2(WIDTH/4.0,200.) ))).insert(LeftText()) commands.spawn(Text2dBundle( text=Text(text="0", font=asset_server.load("fonts/FiraSans-Bold.ttf", AssetType.FONT, size=font_size), font_size=font_size, color=Color('white') ), transform=Transform(translation=Vector2(3 *WIDTH / 4.0, 200.) ))).insert(RightText()) def input(): time = get_resource(Time) keyboard = get_resource(Keyboard) for (paddle, transform) in Query((Paddle, Transform)): paddle_move = time.delta_seconds * PADDLE_VELOCITY if keyboard.pressed(paddle.up_key): transform.translation.y = max(PADDLE_MIN_MOVE, transform.translation.y - paddle_move) if keyboard.pressed(paddle.down_key): transform.translation.y = min(PADDLE_MAX_MOVE, transform.translation.y + paddle_move) def move_ball(): time = get_resource(Time) for (transform, velocity) in Query((Transform, Velocity), With(Ball)): transform.translation += velocity.value * time.delta_seconds if transform.translation.y <= 0 or transform.translation.y + BALL_WIDTH >= HEIGHT: velocity.value.y = - velocity.value.y def collides(): for ball_transform, velocity in Query((Transform, Velocity), With(Ball)): ball_size = Vector2(BALL_WIDTH, BALL_WIDTH) for paddle_transform, in Query(Transform, With(Paddle)): paddle_size = Vector2(PADDLE_WIDTH, PADDLE_HEIGHT) if collide_aabb(ball_transform.translation, ball_size, paddle_transform.translation, paddle_size): velocity.value.x = - velocity.value.x def score(): score = get_resource(Score) for transform, in Query(Transform,With(Ball)): if transform.translation.x < 0: score.right += 1 transform.translation = Vector2(WIDTH/2,HEIGHT/2) elif transform.translation.x > WIDTH: score.left += 1 transform.translation = Vector2(WIDTH/2,HEIGHT/2) def show_score(): score = get_resource(Score) for text, in Query(Text,With(LeftText)): text.text = f"{score.left}" for text, in Query(Text,With(RightText)): text.text = f"{score.right}" if __name__ == "__main__": App() \ .insert_resource(ClearColor(color=pygame.Color('black'))) \ .insert_resource(WindowDescriptor( title="wonderworld ping", width=WIDTH, height=HEIGHT, resizable=False)) \ .insert_resource(Score(left=0, right=0)) \ .add_plugins(DefaultPlugins()) \ .add_startup_system(setup) \ .add_system(input) \ .add_system(move_ball) \ .add_system(collides) \ .add_system(score) \ .add_system(show_score) \ .run() 
pygame 2.1.2 (SDL 2.0.18, Python 3.9.16) Hello from the pygame community. https://www.pygame.org/contribute.html 

About

Data-oriented Python Game Engine

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages