【Love2d从青铜到王者】第十三篇:Love2d之游戏:射击敌人(Game: Shoot the enemy)

news/2024/5/18 14:27:22 标签: 游戏, 游戏引擎, 游戏程序, 开发语言

在这里插入图片描述

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 🍇一、游戏:射击敌人(Game: Shoot the enemy)
  • 🍈二、任务:创建一个移动的熊猫(Task: Create a moving panda)
  • 🍑三、任务:创造一个移动的蛇(Task: Create a moving snake)
  • 🍐四、任务:能够发射子弹(Task: Be able to shoot bullets)
  • 🍒五、任务:使子弹影响敌人的速度(Task: Make bullets affect the enemy's speed)
  • 🍌六、总结
  • 🍋总结


前言

在这里插入图片描述


🍇一、游戏:射击敌人(Game: Shoot the enemy)

  • 让我们用目前所学的一切来创建一个简单的游戏。你可以随心所欲地阅读关于编程和制作游戏的书籍,但要真正学会,你必须亲自动手。
  • 一个游戏本质上是一堆你必须解决的问题。当你让一个有经验的程序员做PONG的时候,他不会去查a如何制作乒乓球。他们可以将PONG分成不同的问题,并且知道如何解决每一个问题。本章将向你展示如何将一个游戏分成多个任务。
  • 我们要做的游戏很简单:一个敌人在墙上反弹。我们必须拍下来。我们每射一次,敌人就跑得更快一点。当你失手时,游戏就结束了,你必须重新开始。
    在这里插入图片描述
  • 对于这个游戏,我们将使用图像。您可以自由使用自己的图像,但我将使用这3种图像:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 这些图像是由kenney,他制作了许多任何人都可以在他们的游戏中使用的免费资源。看看他。
  • 让我们从3个主要回调开始,load classic我们用来模拟类的库。
function love.load()
    Object=require("classic")
    require"panda"
    panda=Panda(0,0,150)
end

function love.update(dt)
    panda:update(dt)
end

function love.draw()
    panda:draw()
end
  • 先说主界面。创建一个名为main.lua
  • 我们可以为我们所有的对象创建一个基类,但是因为这是一个非常简单的游戏,所以我们没有基类。尽管我鼓励你在本章末尾通过自己添加一个基类来改进代码。

🍈二、任务:创建一个移动的熊猫(Task: Create a moving panda)

  • 创建熊猫类别:
Panda=Object:extend()

function Panda:new(x,y,speed)
    self.x=x
    self.y=y
    self.speed=speed
    self.image=love.graphics.newImage("panda.png")
end
  • 我要把熊猫形象给我的玩家。
function Panda:draw()
    love.graphics.draw(self.image,self.x,self.y)
end
  • 接下来让我们用箭头键移动我们的熊猫。
function Panda:update(dt)
    if love.keyboard.isDown("left")
    then
        self.x=self.x-self.speed*dt
    elseif love.keyboard.isDown("right")
    then
        self.x=self.x+self.speed*dt
    end
end

function Panda:draw()
    love.graphics.draw(self.image,self.x,self.y)
end
  • 现在我们应该可以移动我们的熊猫了。让我们回到main.lua。加载我们的panda。。
function love.load()
    Object=require("classic")
    require"panda"
    panda=Panda(0,0,150)
end

function love.update(dt)
    panda:update(dt)
end

function love.draw()
    panda:draw()
end
  • 如你所见,我们可以移动我们的熊猫。但是我们的熊猫可以跳出窗外。让我们用if语句来解决这个问题。
    在这里插入图片描述
Panda=Object:extend()

function Panda:new(x,y,speed)
    self.x=x
    self.y=y
    self.speed=speed
    self.image=love.graphics.newImage("panda.png")

    --获取图片的宽度
    self.width=self.image:getWidth()
end

function Panda:update(dt)
    if love.keyboard.isDown("left")
    then
        self.x=self.x-self.speed*dt
    elseif love.keyboard.isDown("right")
    then
        self.x=self.x+self.speed*dt
    end

    --获取窗口的宽度
    local window_width=love.graphics.getWidth()
    if self.x<0
    then
        self.x=0
    elseif self.x>window_width-self.width
    then
        self.x=window_width-self.width
    end
end

function Panda:draw()
    love.graphics.draw(self.image,self.x,self.y)
end
  • 现在修好了。我们的熊猫不能再跳出窗外了。
    在这里插入图片描述

🍑三、任务:创造一个移动的蛇(Task: Create a moving snake)

  • 现在让我们创建射类。创建一个名为snake.lua,并键入以下内容:
Snake=Object:extend()

function Snake:new(x,y)
    self.x=x
    self.y=y
end
  • 我要给一个蛇的形象,让它自己移动。
Snake=Object:extend()

function Snake:new(x,y)
    self.x=x
    self.y=y
    self.speed=100
    self.image=love.graphics.newImage("snake.png")
end

function Snake:update(dt)
    self.x=self.x+self.speed*dt
end

function Snake:draw()
    love.graphics.draw(self.image,self.x,self.y)
end
  • 我们需要让蛇移动到墙上,但我们先加载蛇。
function love.load()
    Object=require("classic")
    require"panda"
    require"snake"
    panda=Panda(0,0,150)
    snake=Snake(0,love.graphics.getHeight())
end

function love.update(dt)
    panda:update(dt)
    snake:update(dt)
end

function love.draw()
    panda:draw()
    snake:draw()
end
  • 好了,现在我们可以看到蛇在移动,我们可以看到它从我们的窗口移动出去。让我们确保它不会像熊猫一样移出我们的窗口。
    在这里插入图片描述
Snake=Object:extend()

function Snake:new(x,y)
    self.x=x
    self.y=y
    self.speed=100
    self.image=love.graphics.newImage("snake.png")

    --图片高度与宽度
    self.width=self.image:getWidth()
    self.height=self.image:getHeight()
end

function Snake:update(dt)
    self.x=self.x+self.speed*dt

    --窗口宽度
    local window_width=love.graphics.getWidth()
    if self.x<0 
    then
        self.x=0
    elseif self.x+self.width>window_width
    then
        self.x=window_width-self.width
    end
end

function Snake:draw()
    love.graphics.draw(self.image,self.x,self.y)
end

在这里插入图片描述

  • 我们的蛇停在墙边,但我们想让它反弹回来。我们如何让它做到这一点?它撞上了右边的墙,然后呢?它应该向另一个方向移动。我们如何让它向另一个方向移动?通过更改的值speedspeed的值应该是变成什么?不应该是100而是-100。
  • 那么我们应该做什么self.speed = -100- ?不,因为就像我之前说的,我们会让舌头在被击中时加速,这样它在反弹时会重设speed。相反,我们应该反转speed。因此speed成为-speed。换句话说,如果speed增加到120,它就会变成-120。
  • 如果它撞到左边的墙呢?在这一点上,speed是一个负数,我们应该把它变成正数。我们如何做到这一点?嗯,负乘以负等于正。所以如果我们这么说speed,此时为负数,变成-speed,它会变成一个正数。
Snake=Object:extend()

function Snake:new(x,y)
    self.x=x
    self.y=y
    self.speed=100
    self.image=love.graphics.newImage("snake.png")

    --图片高度与宽度
    self.width=self.image:getWidth()
    self.height=self.image:getHeight()
end

function Snake:update(dt)
    self.x=self.x+self.speed*dt

    --窗口宽度
    local window_width=love.graphics.getWidth()
    if self.x<0
    then
        self.x=0
        self.speed=-self.speed
    elseif self.x+self.width>window_width
    then
        self.x=window_width-self.width
        self.speed=-self.speed
    end
end

function Snake:draw()
    love.graphics.draw(self.image,self.x,self.y)
end

在这里插入图片描述

好了,我们有了一个熊猫和一个移动的蛇,现在只剩下子弹了。

🍐四、任务:能够发射子弹(Task: Be able to shoot bullets)

  • 创建一个名为bullet.lua,并编写以下代码:
Bullet=Object:extend()

function Bullet:new()
    self.image=love.graphics.newImage("bullet.png")
end

function Bullet:draw()
    love.graphics.draw(self.image)
end
  • 这个子弹应该垂直向下移动,而不是水平左右移动。
Bullet=Object:extend()

function Bullet:new(x,y)
    self.image=love.graphics.newImage("bullet.png")
    self.x=x
    self.y=y
    self.speed=700
end

function Bullet:update(dt)
    self.y=self.y+self.speed*dt
end

function Bullet:draw()
    love.graphics.draw(self.image,self.x,self.y)
end
  • 在我们需要能够发射子弹。在main.lua中加载文件并创建一个表listOfBullets
function love.load()
    Object=require("classic")
    require"panda"
    require"snake"
    require"bullet"
    panda=Panda(0,0,150)
    snake=Snake(0,love.graphics.getHeight()-105)

    listOfBullets = {}
end

function love.update(dt)
    panda:update(dt)
    snake:update(dt)
end

function love.draw()
    panda:draw()
    snake:draw()
end
  • 现在我们给熊猫一个函数,当空格被按下时会产生一个子弹。
function Panda:keypress(key)
    if key=="space"
    then
        table.insert(listOfBullets,Bullet(self.x,self.y))
    end
end
  • 我们需要调用这个函数在love.keypressed回调。
function love.load()
    Object=require("classic")
    require"panda"
    require"snake"
    require"bullet"
    panda=Panda(0,0,150)
    snake=Snake(0,love.graphics.getHeight()-105)

    listOfBullets = {}
end

function love.keypressed(key)
    panda:keypress(key)
end

function love.update(dt)
    panda:update(dt)
    snake:update(dt)
end

function love.draw()
    panda:draw()
    snake:draw()
end
  • 现在我们需要遍历这个表listOfBulletsupdate/draw所有子弹。
function love.load()
    Object=require("classic")
    require"panda"
    require"snake"
    require"bullet"
    panda=Panda(0,0,150)
    snake=Snake(0,love.graphics.getHeight()-105)

    listOfBullets = {}
end

function love.keypressed(key)
    panda:keypress(key)
end

function love.update(dt)
    panda:update(dt)
    snake:update(dt)

    for k,v in ipairs(listOfBullets)
    do
        v:update(dt)
    end
end

function love.draw()
    panda:draw()
    snake:draw()

    for k,v in ipairs(listOfBullets)
    do
        v:draw()
    end
end

在这里插入图片描述

  • 太棒了,我们的玩家现在可以发射子弹了。

🍒五、任务:使子弹影响敌人的速度(Task: Make bullets affect the enemy’s speed)

  • 现在我们需要让蛇被子弹击中。我们给Bullet一个碰撞检测功能。
function Bullet:checkCollision(obj)
end
  • 你还知道怎么做吗?你还知道保证碰撞发生需要满足的四个条件吗?
  • 我们不是返回真假,而是增加敌人的速度。我们给予变量self_dead给子弹,我们将用它从listOfBullets中删除它。
Bullet=Object:extend()

function Bullet:new(x,y)
    self.image=love.graphics.newImage("bullet.png")
    self.x=x
    self.y=y
    self.speed=700

    self.width=self.image:getWidth()
    self.height=self.image:getHeight()
end

function Bullet:update(dt)
    self.y=self.y+self.speed*dt
end

function Bullet:draw()
    love.graphics.draw(self.image,self.x,self.y)
end

function Bullet:checkCollision(obj)

    --子弹的左右上下
    local self_left=self.x
    local self_right=self.x+self.width
    local self_top=self.y
    local self_bottom=self.y+self.height

    --蛇的左右上下
    local obj_left=obj.x
    local obj_right=obj.x+obj.width
    local obj_top=obj.y
    local obj_bottom=obj.y+obj.height

    if self_left<obj_right 
    and self_right>obj_left
    and self_top<obj_top
    and self_bottom>obj_bottom
    then
        self.dead=true
        obj.speed=obj.speed+50
    end
end
  • 现在我们需要在main.lua中调用checkCollision
function love.update(dt)
    panda:update(dt)
    snake:update(dt)

    for k,v in ipairs(listOfBullets)
    do
        v:update(dt)

        v:checkCollision(snake)
    end
end
  • 接下来我们需要销毁已经self_dead的子弹。
function love.load()
    Object=require("classic")
    require"panda"
    require"snake"
    require"bullet"
    panda=Panda(0,0,150)
    snake=Snake(0,love.graphics.getHeight()-105)

    listOfBullets = {}
end

function love.keypressed(key)
    panda:keypress(key)
end

function love.update(dt)
    panda:update(dt)
    snake:update(dt)

    for k,v in ipairs(listOfBullets)
    do
        v:update(dt)

        --每颗子弹检查是否与敌人有碰撞
        v:checkCollision(snake)

        --如果子弹的属性是self_dead的,那么这是真的
        if v.dead==true
        then
            --从列表中删除它
            table.remove(listOfBullets,k)
        end
    end
end

function love.draw()
    panda:draw()
    snake:draw()

    for k,v in ipairs(listOfBullets)
    do
        v:draw()
    end
end
  • 最后要做的是当我们错过敌人时重启游戏。我们需要检查子弹是否在屏幕外。
function Bullet:update(dt)
    self.y=self.y+self.speed*dt

    --如果子弹不在屏幕上
    if self.y>love.graphics.getHeight()
    then
        --重新开始游戏
        love.load()
    end
end

在这里插入图片描述

  • 让我们来测试一下。你可能会注意到,当你击中向左移动的敌人时,它会减速。这是因为此时敌人的速度是负数。所以通过增加数量,敌人的速度会慢下来。为了解决这个问题,我们需要检查敌人的速度是否是负数。
    在这里插入图片描述
Bullet=Object:extend()

function Bullet:new(x,y)
    self.x=x
    self.y=y
    self.speed=700
    self.image=love.graphics.newImage("bullet.png")

    self.width=self.image:getWidth()
    self.height=self.image:getHeight()
end

function Bullet:update(dt)
    self.y=self.y+self.speed*dt

    --如果子弹不在屏幕上
    if self.y>love.graphics.getHeight()
    then
        --重新开始游戏
        love.load()
    end
end

function Bullet:draw()
    love.graphics.draw(self.image,self.x,self.y)
end

function Bullet:checkCollision(obj)

    --子弹的左右上下
    local self_left=self.x
    local self_right=self.x+self.width
    local self_top=self.y
    local self_bottom=self.y+self.height

    --蛇的左右上下
    local obj_left=obj.x
    local obj_right=obj.x+obj.width
    local obj_top=obj.y
    local obj_bottom=obj.y+obj.height

    if self_left<obj_right and
         self_right>obj_left and
         self_top<obj_bottom and
         self_bottom>obj_top
    then
        self.dead=true

        ---增加蛇的速度
        if obj.speed>0 
        then
            obj.speed=obj.speed+50
        else
            obj.speed=obj.speed-50
        end
    end
end

在这里插入图片描述

  • 我们的游戏到此结束。或者是?你应该试着自己给游戏添加功能。或者做一个全新的游戏。只要你坚持学习,坚持做游戏,都没关系!

🍌六、总结

  • 一个游戏本质上就是一堆需要解决的问题。

🍋总结

以上就是今天要讲的内容,本文仅仅简单介绍了Love2d之碰游戏:射击敌人(Game: Shoot the enemy),介绍了游戏:射击敌人(Game: Shoot the enemy)与及碰撞检测(Detecting collision)的深层使用,与博主的lua语言文章结合更好的理解love2d的编码,如果你是一名独立游戏开发者,或者一位对游戏开发有着深厚兴趣,但是又对于unity3d,ue4等这些对于新手而言不太友好的引擎而头疼的开发者;那么现在,你可以试试Love2D。Love2D是一款基于Lua编写的轻量级游戏框架,尽管官方称呼其为引擎,但实际上它只能称得上是一个框架,因为他并没有一套全面完整的解决方案。不过,这款框架上手及其容易,是学习游戏开发的初学者入门的一个良好选择。

在这里插入图片描述


http://www.niftyadmin.cn/n/1739743.html

相关文章

【Love2d从青铜到王者】第十四篇:Love2d之分享你的游戏(Distributing your game)

系列文章目录 文章目录系列文章目录前言&#x1f347;一、分享你的游戏&#xff08;Distributing your game&#xff09;&#x1f34a;二、castle&#x1f34c;三、总结&#x1f34b;总结前言 &#x1f347;一、分享你的游戏&#xff08;Distributing your game&#xff09; 我…

【Love2d从青铜到王者】第十五篇:Love2d之角度和距离(Angles and distance)

系列文章目录 文章目录系列文章目录前言&#x1f347;一、角度&#xff08;Angle&#xff09;&#x1f34a;二、正弦和余弦&#xff08;Sine and cosine&#xff09;&#x1f351;三、距离&#xff08;Distance&#xff09;&#x1f348;四、图像&#xff08;Image&#xff09;…

Lua热补丁方案(HotFix)

文章目录一、lua基础之热更新二、hotfix 实现了Lua热更新&#xff0c;仅对函数作替换&#xff0c;保留旧数据三、热更新介绍1.原理2.要点分析3.Lua热更新的实现4._ENV 环境变量5.上值 upvalue6.热更新函数Lua的require函数7.热更新函数Lua的setenv函数8.热更新函数Lua的debug库…

【Love2d从青铜到王者】第十六篇:Love2d之动画(Animation)

系列文章目录 文章目录系列文章目录前言&#x1f347;一、Love2d动画&#xff08;Animation&#xff09;1️⃣.框架2️⃣.四角型&#xff08;Quads&#xff09;3️⃣.多行&#xff08;Multiple rows&#xff09;4️⃣.出血的&#xff08;Bleeding&#xff09;5️⃣.总结&#x…

【游戏客户端与服务器面试题】-- 2022年最新游戏客户端与服务器面试(lua篇持续更新)

【游戏客户端与服务器面试题干货】-- 2022年度最新游戏客户端面试干货(lua篇&#xff09; 文章目录一、Lua的8种数据类型(1) nil 类型(2) boolean类型(3) number类型1.加&#xff0c;减-&#xff0c;乘*&#xff1a;2.除/&#xff1a;3.双除法 // &#xff1a;4.取整&#xff1…

gcc/g++编译过程、system系统调用过程

文章目录一、system系统调用1.实例1&#xff1a;01_test.c2.实例2&#xff1a;02_waibu.c3.实例3&#xff1a;03_system.c4.实例4&#xff1a;calc 计算器二、gcc/g编译1.预处理&#xff1a;gcc -E hello.c -o hello.i2.编译&#xff1a; gcc -S hello.i -o hello.s3.汇编&…

VScode用控制台输出中文乱码

当我们第一次用VScode编写C或C代码或者其他语言代码时候会发现用控制台输出的中文汉字却是乱码&#xff0c;如下图&#xff1a; 这是因为我们的控制台编码是GBK编码。C/C语言的运行程序是调用的cmd.exe&#xff0c;而window的cmd的编码默认为936也就是GB2312。运行—>cmd—…

lua踩坑之浅拷贝与深拷贝

文章目录一、前言二、浅拷贝和深拷贝三、浅拷贝1.拷贝对象为string、number、boolean等基础类型时2.拷贝对象的类型为table类型时三、深拷贝一、前言 先来说说&#xff0c;为什么突然谈及到浅拷贝和深拷贝这个问题。因为时间紧任务重&#xff0c;lua零基础参与项目研发&#x…