goplus / spx

spx - A Scratch Compatible Go/Go+ 2D Game Engine for STEM education
https://builder.goplus.org
Apache License 2.0
100 stars 28 forks source link

Type definition for sprite #316

Open nighca opened 3 weeks ago

nighca commented 3 weeks ago

Consider a modified version of the game AircraftWar where instead of firing bullets, the aircraft uses lasers to destroy enemies. The laser immediately eliminates the nearest enemy at the same xpos when fired.

Implementing this using the touching and onTouched API is not feasible because:

In this scenario, game developers may need to manage a global sprite array, which simplifies the logic:

// main.spx

var (
    enemies []Sprite
)

func onPlayerAttack() {
    // Locate the nearest enemy with the same xpos as the player
    // Iterate through `enemies` and use `enemy.xpos()` / `enemy.ypos()`
}
// Enemy.spx

onCloned => {
    enemies = append(enemies, this)
}

However, there’s a complication: spx lacks an appropriate type definition for Sprite.

The Sprite type currently refers to a struct, while any enemy in the game is an instance of Enemy:

type Enemy struct {
    spx.Sprite
    *Game
}

So it is inappropriate to use []Sprite to store enemy instances.

Using []Enemy for the enemies array is inappropriate either because:

I propose renaming the existing type Sprite struct{} to SpriteImpl and defining a new type Sprite:

type Sprite interface {
    Visible() bool
    Xpos() float64
    Ypos() float64
    // Any methods intended for game developers will be defined in this interface
}

type SpriteImpl struct {
    // Additionally, `*SpriteImpl` will implement `Sprite`, as will sprite classes like `*Enemy`
}

With this structure, the sprite array logic will function as intended.

Please share your ideas here, @xushiwei @JiepengTan.

JiepengTan commented 3 weeks ago

@nighca In game development, interfaces from the physics engine are typically used to implement the above business requirements e.g., Physics2D.Raycast, Physics2D.OverlapBox ...

The following are some of Unity's API interfaces:

  public static RaycastHit2D Raycast(Vector2 origin, Vector2 direction, float distance)
  public static RaycastHit2D[] RaycastAll(Vector2 origin,Vector2 direction,float distance,int layerMask)
  public static Collider2D OverlapBox(Vector2 point, Vector2 size, float angle)
  public static Collider2D[] OverlapBoxAll(Vector2 point,Vector2 size,float angle,int layerMask,float minDepth)
nighca commented 2 weeks ago

interfaces from the physics engine are typically used to implement the above business requirements e.g., Physics2D.Raycast, Physics2D.OverlapBox ...

@JiepengTan These seem to be more basic definitions, like Shape in spx.

What I propose to add is a type definition which just describes a sprite. All public methods that a sprite has, e.g., Die/Say/Step/..., will be declared on this type definition.