坦克大战-kotlin

坦克大战

    • 游戏需求
      • 核心玩法
      • 界面原型
      • 成品演示
    • 游戏开发
      • 1.代码实现
    • 源码下载

专栏简介

个人主页
专栏目录

点击上方查看更多内容
心灵鸡汤
人生中,有些事情是我们可以掌控的,把握得好,我们会拥有更多的成功机会,即使失败,也不会怨天尤人。
欢迎订阅!收藏!

游戏需求

  仿照IT黑马kotlin教程中的坦克大战,在它的基础上做了以下升级:
  1.增加侧边栏,显示敌我双方的坦克数量
  2.敌方坦克生成的同时,随机生成不同样式的坦克
  3.追加坦克打击视图

核心玩法

  1️⃣.经典坦克大战

界面原型

主图采用9X9布局,侧边栏使用3X9

成品演示

坦克大战-kotlin_第1张图片

游戏开发

   下面就总结下实现过程。

gradle 7.4.2
jdk 1.8

我这里只贴与it黑马kotlin教程中的演示代码不同部分。代码并非完整代码

1.代码实现

1.build.gradle.kts 配置

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.7.10"
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
    maven{url=uri("https://jitpack.io")}
}

dependencies {
    testImplementation(kotlin("test"))
    implementation("com.github.shaunxiao:kotlinGameEngine:v0.0.4")
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

2.我方坦克
限制坦克连接发射,防止持续按Enter时子弹持续发射

  //发射频率限制-防止一直按着发射键时,循环发射
    var lastShot=0L
    var shotSpeed=500

fun shot():Bullet?{
        var currentTimeMillis = System.currentTimeMillis()
        //连击限制
        if (currentTimeMillis-lastShot>=shotSpeed){
            lastShot=currentTimeMillis
        }  else {
            return null
        }
        var bulletX=0
        var bulletY=0
        var bulletWidth=17
        var bulletHeight=17
        when(crueeDirection){
            Direction.UP->{
                bulletX=x+(width-bulletWidth)/2
                bulletY=y-bulletHeight
            }
            Direction.DOWN->{
                bulletX=x+(width-bulletWidth)/2
                bulletY=y+height
            }
            Direction.LEFT->{
                bulletX=x-bulletWidth
                bulletY=y+(height-bulletHeight)/2
            }
            Direction.RIGHT->{
                bulletX=x+width
                bulletY=y+(height-bulletHeight)/2
            }
            else -> {}
        }
        Composer.play("sond/fire.wav")
        return Bullet(crueeDirection,bulletX,bulletY,this)
    }

3.敌方坦克视图样式随机生成

//绘制
    var i = Random.nextInt(1..2)
    override fun drow() {
        println(i)
        var imgPath = when (crueeDirection) {
            Direction.UP -> "/img/enemy${i}U.gif"
            Direction.DOWN -> "/img/enemy${i}D.gif"
            Direction.LEFT -> "/img/enemy${i}L.gif"
            Direction.RIGHT -> "/img/enemy${i}R.gif"
            else -> {"/img/p1tankU.gif"}
        }
        Painter.drawImage(imgPath,x,y)
    }

4.坦克(墙面)受击视图反馈 (追加相应音效)
两种视图,一种为受击不销毁,一种为受击销毁视图

 override fun notifySuffer(attackAble: AttackAble): Array<View>? {
        if (attackAble.woner is Enemy){
            //自己打自己不反应
            return null
        }
        blood-=attackAble.atk
        if (blood==0){
            Composer.play("sond/blast.wav")
            return arrayOf(Blast(x-30,y-30))
        }else{
            Composer.play("sond/hit.wav")
            return arrayOf(Born(x,y))
        }
    }

5 侧边栏绘制 Bar.ks

    class Bar(override val x: Int, override val y: Int) :View {
    
        override val width: Int=60
        override val height: Int=60
    
        override fun drow() {
            Painter.drawImage("/img/bar.jpeg",x,y)
            Painter.drawText("敌方坦克:",x,y+30, Color.BLACK, Font.font(20.00))
            Painter.drawText("我方坦克:",x,Config.gameHeight-100, Color.BLACK, Font.font(20.00))
        }
    
    }

6.创建BarAble

interface BarAble:View {
}

7.创建MiniTank.ks 和 TankLife.ks 用于侧边栏中敌方坦克和我方坦克数量的展示

class MiniTank(override var x: Int, override var y: Int,var totalTank:Int) :BarAble {


    override val width: Int = 30
    override val height: Int =30

    var nowTankCount=totalTank;

    var indexLst= arrayListOf<Pair<Int,Int>>()
    init {
        var tankX=x+5
        var tankY=y+40
        var index=0
        (0..nowTankCount).forEach {
            if (index==5){
                tankX=x+5
                tankY+=40
                indexLst.add(Pair(tankX,tankY))
                index=0
            }else{
                indexLst.add(Pair(tankX,tankY))
            }
            tankX+=35
            index++
        }
    }

    override fun drow() {
        var i=0
        indexLst.forEach { index->
            if (i>=nowTankCount){
            }else{
                Painter.drawImage("img/mintank.gif",index.first,index.second)
            }
            i++
        }
    }
}

8.敌我双方坦克数量在侧边栏重新绘制

views.filter {  it is DestoryAble }.forEach { dis->
            dis as DestoryAble
            if (dis.isDestory()){
                views.remove(dis)
                if (dis is Enemy){
                    totalEnemyNum--
                    views.filter {  it is MiniTank }.forEach { mini->
                        mini as MiniTank
                        views.remove(mini)
                        //bar 处理
                        views.add(MiniTank(Config.gameWidth,0,totalEnemyNum))
                    }
                }

                if (dis is PTank){
                    totolMyTank--
                    views.filter {  it is TankLife }.forEach { mini->
                        mini as TankLife
                        views.remove(mini)
                        if (totolMyTank>0){
                            tank=PTank(Config.block*7,Config.block*8)
                            views.add(tank)
                        }
                        //bar 处理
                        views.add(TankLife(Config.gameWidth,Config.gameHeight-130,totolMyTank))
                    }
                }
            }
        }

9.结束判断

        if ((views.filter { it is Camp }.isEmpty()) or (totalEnemyNum<=0) or(totolMyTank<=0)) gameOver=true

10.结束视图

 if (gameOver){
            Painter.drawImage("img/over.gif",Config.block*4,Config.block*4)
            return
        }

源码下载

源码下载
营业公告 源码获取
工作日:早8:30-晚5:30
可在下方留言获取源码

你可能感兴趣的:(H5游戏,kotlin,开发语言,android)