用Go写一个《植物大战僵尸》小游戏:支持鼠标放僵尸、胜利失败判定!

你有没有想过,用 Go语言 也能写小游戏?今天就带大家用不到 200 行代码,打造一个简版《植物大战僵尸》!

不仅能 自动射击判断胜负,还可以 用鼠标点击放僵尸挑战自己,实现真正的人机对抗!


游戏玩法

  • • 植物固定位置自动发射子弹
  • • 点击鼠标左键放置僵尸,向左移动
  • • 子弹打中僵尸可造成伤害,击败 10 个获胜!
  • • 有僵尸闯进防线则游戏失败

技术点

  • • 游戏开发框架:Ebiten
  • • 植物发射逻辑:定时自动生成子弹
  • • 僵尸行为:匀速向左移动,碰到子弹扣血
  • • 鼠标点击:在任意位置生成僵尸
  • • 游戏结局:胜利 or 失败提示

完整代码(Go + Ebiten)

package main

import (
    "fmt"
    "image/color"
    "log"
    "math"
    "math/rand"
    "time"

    "github.com/hajimehoshi/ebiten/v2"
    "github.com/hajimehoshi/ebiten/v2/ebitenutil"
)

type Zombie struct {
    x, y float64
    hp   int
}

type Bullet struct {
    x, y float64
}

type Game struct {
    zombies       []Zombie
    bullets       []Bullet
    shootCD       int
    mouseDown     bool
    zombiesKilled int
    gameOver      bool
    gameWin       bool
}

func (g *Game) Update() error {
    if g.gameOver {
        return nil
    }

    // 自动发射子弹
    if g.shootCD <= 0 {
        g.bullets = append(g.bullets, Bullet{x: 100, y: 200})
        g.shootCD = 15
    } else {
        g.shootCD--
    }

    // 更新子弹
    newBullets := []Bullet{}
    for _, b := range g.bullets {
        b.x += 6
        if b.x < 800 {
            newBullets = append(newBullets, b)
        }
    }
    g.bullets = newBullets

    // 更新僵尸
    newZombies := []Zombie{}
    for _, z := range g.zombies {
        z.x -= 1.2
        if z.x <= 0 {
            g.gameOver = true
            g.gameWin = false
            return nil
        }

        hit := false
        for i := range g.bullets {
            if math.Abs(z.x-g.bullets[i].x) < 10 && math.Abs(z.y-g.bullets[i].y) < 10 {
                z.hp--
                if z.hp <= 0 {
                    hit = true
                    g.zombiesKilled++
                    if g.zombiesKilled >= 10 {
                        g.gameOver = true
                        g.gameWin = true
                        return nil
                    }
                    break
                }
            }
        }
        if !hit {
            newZombies = append(newZombies, z)
        }
    }
    g.zombies = newZombies

    // 鼠标左键放僵尸
    if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
        if !g.mouseDown {
            x, y := ebiten.CursorPosition()
            g.zombies = append(g.zombies, Zombie{
                x:  float64(x),
                y:  float64(y),
                hp: 3,
            })
            g.mouseDown = true
        }
    } else {
        g.mouseDown = false
    }

    return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
    screen.Fill(color.RGBA{0xCC, 0xFF, 0xCC, 0xFF})

    // 植物
    ebitenutil.DrawRect(screen, 100, 200, 20, 20, color.RGBA{0x00, 0x88, 0x00, 0xFF})

    // 子弹
    for _, b := range g.bullets {
        ebitenutil.DrawRect(screen, b.x, b.y, 5, 5, color.RGBA{0x00, 0x00, 0xFF, 0xFF})
    }

    // 僵尸
    for _, z := range g.zombies {
        ebitenutil.DrawRect(screen, z.x, z.y, 20, 20, color.RGBA{0x88, 0x00, 0x00, 0xFF})
    }

    // 文本信息
    msg := "点击鼠标左键放置僵尸! 已击败僵尸:" + itoa(g.zombiesKilled)
    if g.gameOver {
        if g.gameWin {
            msg = " 胜利!你击败了10个僵尸!"
        } else {
            msg = " 游戏失败!有僵尸入侵了!"
        }
    }
    ebitenutil.DebugPrint(screen, msg)
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
    return 800, 600
}

func itoa(n int) string {
    return fmt.Sprintf("%d", n)
}

func main() {
    rand.Seed(time.Now().UnixNano())
    game := &Game{}
    ebiten.SetWindowSize(800, 600)
    ebiten.SetWindowTitle("Go版植物大战僵尸 - 加入胜利/失败判定")
    if err := ebiten.RunGame(game); err != nil {
        log.Fatal(err)
    }
}

编译运行方法

  1. 1. 安装依赖(需要 Go 和 Ebiten):
go get github.com/hajimehoshi/ebiten/v2
  1. 2. 运行程序:
go run main.go

最后

这个小游戏只是开始,后续你可以扩展:

  • • 不同种类植物与僵尸
  • • 子弹特效
  • • 多行战斗区域
  • • 商店系统与阳光资源管理

如果你对游戏开发有兴趣,Go + Ebiten 是一个极具潜力的组合!

你有没有想过,用 Go语言 也能写小游戏?今天就带大家用不到 200 行代码,打造一个简版《植物大战僵尸》!

不仅能 自动射击判断胜负,还可以 用鼠标点击放僵尸挑战自己,实现真正的人机对抗!


游戏玩法

  • • 植物固定位置自动发射子弹
  • • 点击鼠标左键放置僵尸,向左移动
  • • 子弹打中僵尸可造成伤害,击败 10 个获胜!
  • • 有僵尸闯进防线则游戏失败

技术点

  • • 游戏开发框架:Ebiten
  • • 植物发射逻辑:定时自动生成子弹
  • • 僵尸行为:匀速向左移动,碰到子弹扣血
  • • 鼠标点击:在任意位置生成僵尸
  • • 游戏结局:胜利 or 失败提示

完整代码(Go + Ebiten)

package main

import (
    "fmt"
    "image/color"
    "log"
    "math"
    "math/rand"
    "time"

    "github.com/hajimehoshi/ebiten/v2"
    "github.com/hajimehoshi/ebiten/v2/ebitenutil"
)

type Zombie struct {
    x, y float64
    hp   int
}

type Bullet struct {
    x, y float64
}

type Game struct {
    zombies       []Zombie
    bullets       []Bullet
    shootCD       int
    mouseDown     bool
    zombiesKilled int
    gameOver      bool
    gameWin       bool
}

func (g *Game) Update() error {
    if g.gameOver {
        return nil
    }

    // 自动发射子弹
    if g.shootCD <= 0 {
        g.bullets = append(g.bullets, Bullet{x: 100, y: 200})
        g.shootCD = 15
    } else {
        g.shootCD--
    }

    // 更新子弹
    newBullets := []Bullet{}
    for _, b := range g.bullets {
        b.x += 6
        if b.x < 800 {
            newBullets = append(newBullets, b)
        }
    }
    g.bullets = newBullets

    // 更新僵尸
    newZombies := []Zombie{}
    for _, z := range g.zombies {
        z.x -= 1.2
        if z.x <= 0 {
            g.gameOver = true
            g.gameWin = false
            return nil
        }

        hit := false
        for i := range g.bullets {
            if math.Abs(z.x-g.bullets[i].x) < 10 && math.Abs(z.y-g.bullets[i].y) < 10 {
                z.hp--
                if z.hp <= 0 {
                    hit = true
                    g.zombiesKilled++
                    if g.zombiesKilled >= 10 {
                        g.gameOver = true
                        g.gameWin = true
                        return nil
                    }
                    break
                }
            }
        }
        if !hit {
            newZombies = append(newZombies, z)
        }
    }
    g.zombies = newZombies

    // 鼠标左键放僵尸
    if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
        if !g.mouseDown {
            x, y := ebiten.CursorPosition()
            g.zombies = append(g.zombies, Zombie{
                x:  float64(x),
                y:  float64(y),
                hp: 3,
            })
            g.mouseDown = true
        }
    } else {
        g.mouseDown = false
    }

    return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
    screen.Fill(color.RGBA{0xCC, 0xFF, 0xCC, 0xFF})

    // 植物
    ebitenutil.DrawRect(screen, 100, 200, 20, 20, color.RGBA{0x00, 0x88, 0x00, 0xFF})

    // 子弹
    for _, b := range g.bullets {
        ebitenutil.DrawRect(screen, b.x, b.y, 5, 5, color.RGBA{0x00, 0x00, 0xFF, 0xFF})
    }

    // 僵尸
    for _, z := range g.zombies {
        ebitenutil.DrawRect(screen, z.x, z.y, 20, 20, color.RGBA{0x88, 0x00, 0x00, 0xFF})
    }

    // 文本信息
    msg := "点击鼠标左键放置僵尸! 已击败僵尸:" + itoa(g.zombiesKilled)
    if g.gameOver {
        if g.gameWin {
            msg = " 胜利!你击败了10个僵尸!"
        } else {
            msg = " 游戏失败!有僵尸入侵了!"
        }
    }
    ebitenutil.DebugPrint(screen, msg)
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
    return 800, 600
}

func itoa(n int) string {
    return fmt.Sprintf("%d", n)
}

func main() {
    rand.Seed(time.Now().UnixNano())
    game := &Game{}
    ebiten.SetWindowSize(800, 600)
    ebiten.SetWindowTitle("Go版植物大战僵尸 - 加入胜利/失败判定")
    if err := ebiten.RunGame(game); err != nil {
        log.Fatal(err)
    }
}

编译运行方法

  1. 1. 安装依赖(需要 Go 和 Ebiten):
go get github.com/hajimehoshi/ebiten/v2
  1. 2. 运行程序:
go run main.go

最后

这个小游戏只是开始,后续你可以扩展:

  • • 不同种类植物与僵尸
  • • 子弹特效
  • • 多行战斗区域
  • • 商店系统与阳光资源管理

如果你对游戏开发有兴趣,Go + Ebiten 是一个极具潜力的组合!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值