對比python學julia(第三章:遊戲編程)--(第四節)捕魚達人(5)

4.3.    編程實現

(續上)

  3. 實現射擊捕魚

  在第 3 個階段,將按照“編程思路”中介紹的射擊捕魚的算法進行編程,實現讓玩家操控大炮射擊捕魚。在“bydr”項目目錄中,把version2.jl複製一份並命名爲version3.jl,然後在第2個版本的基礎上編寫第3個版本的代碼。

  1)   創建3個角色

  由於GameZero沒有精靈(sprite)的概念,所以我們將game_sprites.jl,改名爲game_actor.jl,並在其中分別創建BulletSprite()函數生成炮彈角色、NetSprite()函數生成漁網角色和CoinSprite()函數生成硬幣角色。

  BulletSprite()函數代碼如下:  

1 function BulletSprite(x,y)
2     #'''炮彈精靈'''
3     actor=Actor(bullet_img)
4     actor.pos=x,y
5     actor.speed = 300
6     actor.alpha=255
7     #self.visible = True
8     return actor
9 end

  炮彈角色有兩個屬性:speed 和 visible,分別用於控制炮彈的移動速度和可見狀態。不過GameZero的Actor沒有visible屬性,但是提供了alpha屬性,這個屬性可以控制Actor的透明度,alpha的值爲0表示完全透明,255表示完全不透明,因此可以用這個屬性達到控制炮彈可見性的目的。

  另外創建函數fire_move()法用於實現炮彈的移動,當炮彈移動到遊戲窗口的可見區域之外,就讓其消失。

 1 function fire_move(bullet::Actor, dt)
 2     #移動炮彈
 3     if bullet.alpha==255
 4         move(bullet,bullet.speed * dt)
 5         if bullet.x < 0 || bullet.x > 1024 || bullet.y > 768
 6             #self.visible = False
 7             bullet.alpha=0
 8         end
 9     end
10 end

  NetSprite()函數代碼如下:

1 function NetSprite(netPos)
2     #'''漁網精靈'''
3     actor=Actor(fishing_net_img,pos=netPos)
4     #self.set_sprite_center()
5     actor.size = 0
6     #actor.visible = True
7     actor.alpha=255
8     return actor
9 end

  漁網角色兩個屬性:size 和 visible,分別用於控制漁網張開的大小和可見性。可見性魚炮彈類同。

  另外,創建open()函數,用於實現讓漁網由小慢慢變大並消失的動態效果。

function open(net::Actor, dt)
    #打開漁網
    if net.scale <= [1,1]
        net.size += 300 * dt
        net.scale = [net.size / 100,net.size / 100]
    else
        #net.visible = false
        net.alpha=0
    end
end

  注意Actor的屬性scale,可對角色圖像進行縮放,它是個含有兩個元素的數組,分別爲橫向和縱向縮放比例,因此它可以非等比縮放。

  CoinSprite()函數的代碼如下:

 1 function CoinSprite(coinPos, score=0)
 2     #'''硬幣精靈'''
 3         #println(silver_coin_img[1])
 4         actor=Actor(silver_coin_img[1],pos=coinPos)
 5         actor.score = score
 6         actor.speed = 400
 7         #actor.visible = True
 8         actor.alpha=255
 9         actor.frame=1
10         actor.set_animation=coin_animation(score,actor)
11         #面向窗口底部的硬幣箱
12         point(actor,160, 597)
13         return actor
14 end

  硬幣角色有3個屬性,Score用於記錄捕獲一條魚的得分,speed和visible分別用於控制硬幣移動速度和可見狀態。類中的 set_animation屬性用於按得分創建銀幣或金幣的動畫圖像。

  這裏就顯現出Julia的獨特之處了!在Julia中處處皆對象。函數也是對象,因此可以將一個函數作爲某個對象的屬性。這裏,硬幣的set_animation屬性就被賦予了一個函數

  actor.set_animation=coin_animation(score,actor)

  而coin_animation()函數是這樣的:

function coin_animation(score,coin::Actor)
    #'''設置硬幣動畫'''
    images = (score <= 20) ? silver_coin_img : gold_coin_img
    function _animation()
        _frame=coin.frame
        if _frame < length(images)
            coin.image = images[_frame]
            _frame += 1
            
        else
            _frame = 1
        end
        coin.frame=_frame
        schedule_once(_animation, 1/16)
    end
    return _animation
end

  另外,創建move_down()函數,控制硬幣的移動,當硬幣移動到計分牌下方時,消失。

  

function move_down(coin::Actor, dt)
    #'''移動硬幣'''
    if coin.y < 600
        move(coin,coin.speed * dt)
    else
        #coin.visible = False
        #println(coin.alpha)
        coin.alpha=0
    end
end

  2)   控制射擊捕魚動

  切換到“version3.jl”源文件,創建fire_control()函數,用於實現發射炮彈捕魚,檢測炮彈與魚的碰撞,以及控制漁網張開、硬幣落下等。

  function fire_control(dt)…end

  從 bullets 列表讀取各個炮彈精靈實例,讓炮彈精靈移動,並與 fishes 列表中的每個魚角色實例進行碰撞檢測。當炮彈角色碰到魚角色時,就讓炮彈消失,並在魚的位置拋出一張漁網。此外,還從 bullets 列表中移除處於不可見狀態的炮彈角色實例。

 1 #'''捕魚控制'''
 2     #炮彈
 3     for bullet in bullets
 4         if bullet.alpha==255
 5             #移動炮彈
 6             fire_move(bullet,dt)
 7             if bullet.y < 150
 8                 continue
 9             end
10             #對每條有生命的魚進行碰撞檢測
11             for fish in fishes
12                 if fish.life <= 0
13                     continue
14                 end
15                 if collide(bullet,fish)
16                     #命中魚減去生命值
17                     fish.life -= 1
18                     #讓炮彈消失
19                     #bullet.visible = False
20                     bullet.alpha=0
21                     #拋撒漁網在炮彈處
22                     throw_fishing_net(fish.pos)
23                 end
24             end                  
25         else
26             #delete!(bullets,bullet)
27             #bullets.remove(bullet)
28             #bullet.delete()
29             filter!(e->e≠bullet,bullets)
30         end
31     end

  從 nets 列表中讀取各個漁網角色實例,讓漁網逐漸張開。當漁網角色處於不可見狀態時,就將其從 nets 列表中移除。

#漁網
    for net in nets
        if net.alpha==255
            open(net,dt)
        else
            #delete!(nets,net)
            #nets.remove(net)
            #net.delete()
            filter!(e->e≠net,nets)
        end
    end

  從 coins 列表中讀取各個硬幣角色實例,讓硬幣角色向着窗口左下角的硬幣盒處移動。 之後 ,將捕魚的得分累加到全局變量 Score 中 ,並將硬幣角色從 coins 列表中移除。

global score_label             
    #硬幣
    for coin in coins
        if coin.alpha==255
            move_down(coin,dt)
        else
            #加分
            global score
            score += coin.score
            score_label = TextActor(@sprintf("%06d",score),"Arial-Black",font_size=24, color=Int[255,255,255,255])
            score_label.pos=(165,635)    
            #score_label.text = '%06d' % score

            #delete!(coins,coin)
            #coins.remove(coin)
            #coin.delete()
            filter!(e->e≠coin,coins)
        end
    end

  至此,函數 fire_contro1( )編寫完畢,在窗口update事件方法裏調用。

  接下來,創建fire_bullet()、throw_fishing_net()和 release_coin()這3 個函數,分別用於實現發射炮彈、拋出漁網和釋放硬幣的功能。在這些函數中將會生成炮彈角色、漁網角色和硬幣角色的實例,將它們加人到對應的bullets、nets或coins列表中。

function fire_bullet()
    #'''發射炮彈'''
    #println(cannon.angle)
    
    bullet = BulletSprite(0,0)
    bullet.angle = cannon.angle
    bullet.x=cannon.x+ (cannon.w-bullet.w)/2
    bullet.y=cannon.y+ (cannon.h-bullet.h)/2
    push!(bullets,bullet)
    #bullets.append(bullet)
end

function throw_fishing_net(pos)
    #'''拋撒漁網'''
    net = NetSprite(pos)
    push!(nets,net)
    #nets.append(net)
end

function release_coin(pos, score)
    #'''釋放金幣'''
    coin = CoinSprite(pos, score)
    coin.set_animation()
    #coin_animation(coin,score)
    push!(coins,coin)
    #coins.append(coin)
end 

  在遊戲窗口中按下鼠標左鍵時,將調用 fire_bullet() 函數發射炮彈。

function on_mouse_down(g::Game, pos, button)
    if button==MouseButtons.LEFT
        #println("在窗口'$pos'處按下左鍵")
        fire_bullet()
    end
end

  還要在遊戲窗口的事件draw()方法中調用 draw_actor()函數,將 nets、coins和bullets 這 3 個列表中的漁網、硬幣和炮彈角色實例的圖像繪製到窗口中。  

function draw(g::Game)
    clear()
    draw_actor(fishes)
    draw_actor(nets)
    draw_actor(coins)
    draw(panel)
    draw(score_label)
    draw_actor(bullets)
    draw(cannon)
end

  至此,這個遊戲程序的第3個版本完成。運行程序,就能讓玩家操控大炮發射炮彈捕魚了。趕快試試吧!

  4.   播放背景音樂

  看着賞心悅目的畫面,再配上悅耳動聽的音樂,將讓遊戲體驗更佳。這是第 4 個階段要實現的功能,請自行實現。

  源碼下載:https://files.cnblogs.com/files/zjzkiss/bydr_v3.rar

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章