搜索
有爱,有技术,有你^_^)y
╱人◕‿‿◕人╲订下契约(注册新用户)

合作站点账号登陆

QQ登录

只需一步,快速开始

快捷导航
查看: 1092|回复: 8
收起左侧

Go与SDL写小游戏(三)----井字游戏

[复制链接]

该用户从未签到

30

主题

127

好友

2万

积分

技术宅认证程序员

重度中二患者

积分
28325
发表于 2013-4-2 01:03:56 | 显示全部楼层 |阅读模式

╱人◕‿‿◕人╲定下契约

您需要 登录 才可以下载或查看,没有账号?╱人◕‿‿◕人╲订下契约(注册新用户)

x
本帖最后由 foodszhu 于 2013-4-2 01:03 编辑

无聊啊无聊啊
前面两篇:
配置篇
Hello World篇

-----------------------------------------------------------------------------------------------------------------------

这次我们真正尝试一个稍微像游戏的东西--井字游戏。。。就是那种在 3 X 3方格中画O和X,如果三个连成一线就是胜利。。虽然这东西已经证明先手必胜(不败),但是作为最基础的游戏。就来稍微做一下吧

首先准备一个3 X 3的网格。。。大小为600 X 600 back_ground.png
好吧。。。。我不会用GIMP。。。。。自己手画就这么丑。。。。求不喷死。。。
再准备一下O和X的图片。。。这次我们把他们放到一起,一个200 X 400 的图片 ox.png
(如果能自己画的话还是自己画吧。。。我这个太丑了。。泪奔)

这次我们将尝试事件驱动的编程
[mw_shl_code=applescript,true]package main

import (
        "github.com/banthar/Go-SDL/sdl"
)

func main() {
        var back_ground, ox, screen *sdl.Surface[/mw_shl_code]
包名,引入包名,主函数,界面surface声明
[mw_shl_code=applescript,true]        logic_plane := [3][3]int{}
        running := true
        turn := true[/mw_shl_code]
逻辑板的声明。。一个3X3的数组。。。
Go语言中数组定义方方式 "[n]<type>" 有点古怪。长度下标 n 必须是编译期正整数常量 (或常量表达式)。 长
度是类型的组成部分,也就是说 "[10]int" 和 "[20]int" 是完全不同的两种数组类型。数组是值类型,也就是说会拷⻉贝整个数组内存进行行值传递。可用用 slice 或指针代替。(跟C不同哦)
可以用用 new() 创建数组,返回数组指针。var a = new([10]int)
[mw_shl_code=applescript,true]        sdl.Init(sdl.INIT_EVERYTHING)
        defer sdl.Quit()
        screen = sdl.SetVideoMode(600, 600, 32, sdl.SWSURFACE)
        back_ground = sdl.Load("back_ground.png")
        ox = sdl.Load("ox.png")
        defer back_ground.Free()
        defer ox.Free()
        sdl.WM_SetCaption("井字游戏", "")[/mw_shl_code]
依旧是老套的初始化与图片的读取,释放。窗口标题的设置。。

下面进入核心事件循环
在SDL中,每当有一个事件发生, 它会被置于事件队列中。事件队列为每个发生的事件保存了事件数据。
        
所以如果你按一下鼠标按钮,再移动一下鼠标,接着再按下键盘上某个按键,事件队列看起来会像这样:
                 

                               
登录/注册后可看大图

我们将用一个循环反复捕捉事件。。并且读取事件来驱动整个程序的运作
首先,先说Go的循环
for 支持三种形式:
for init; condition; post {}
for condition {}
for {}        
第一种就是C语言的for循环,初始化,判断条件,步进值
第二种就类似while循环,当condition = false时退出循环
第三种就是 while(1),无限循环,只能通过break来退出循环(goto也可,不推荐)
当然go还提供range保留字和for搭配产生迭代器的效果。(很类似python,不过没那么好用,而且基本都是提前算好,不是真正意义上的迭代器)

我们利用running变量判断程序是否进行
[mw_shl_code=applescript,true]for running {
                event := sdl.PollEvent()
                switch e := event.(type) {
                //switch a.(type)检查接口a的类型,然后e就相当于转换了接口的类型
                case *sdl.QuitEvent:
                        running = false
                        return[/mw_shl_code]
sdl.PollEvent函数左右是从消息队列里提取出一个事件,并返回。返回值是sdl.Event,sdl.Event是一个接口。。。
这里接口解释起来比较复杂。。。
所谓接口。。我们简单认为就是满足一定特性的一系列事物,对于Go,就是他一定拥有某些方法,对于一个接口,它实际存储的可能是任何类型,但都必须有某个方法。。这样便实现了多态。。这里因为还没说方法。。就先不多说接口问题,

switch语句用于多路选择,在各个语言中都有涉及,不过Go语言明显吸取了C的教训,switch中case语句可以跟任何类型的常量/变量,而且默认case语句后自带break,也就是不会从一个case语句跑到另一个中,如果真需要这样做,必须显式使用fallthrough来修饰。。。同样有default来进行默认情况的匹配

而我们这里,用一个switch比较特别的用法,swith a.(type)
a.(type)这种用法仅能在switch语句中使用,用来匹配a的类型 结果返回a的类型。
而这里我们由于event是一个接口,所以它返回的一定是它所存储的数据的类型,由于接口存储的必然是指针,所以我们就可以由此判断
sdl.QuitEvent是离开的事件,也就是窗口点x,右键退出等所响应的事件
我们将running = false。意味循环结束

[mw_shl_code=applescript,true]                case *sdl.MouseButtonEvent:
                        if e.Type == sdl.MOUSEBUTTONDOWN {
                                switch e.Button {
                                case sdl.BUTTON_RIGHT:
                                        for i := 0; i < 3; i++ {
                                                for j := 0; j < 3; j++ {
                                                        logic_plane[j] = 0
                                                }
                                        }
                                case sdl.BUTTON_LEFT:
                                        i := e.X / 200
                                        j := e.Y / 200
                                        if logic_plane[j] == 0 {
                                                if turn {
                                                        turn = !turn
                                                        logic_plane[j] = 1
                                                } else {
                                                        turn = !turn
                                                        logic_plane[j] = 2
                                                }
                                        }
                                }
                        }
                }[/mw_shl_code]
下面我们匹配鼠标事件,如果鼠标右键单击,则游戏重新开始,
左键单击,则在逻辑板中进行变化。每点一次turn切换一次,意味这两个人交替下子。

最后我们将一下精灵图的概念

当我们需要一系列较小图片来组成整个程序时,我们往往不希望每一个小图片都是一个独立的文件,这样无疑使得读取更加费时,操作更加复杂,所以提出了精灵图的概念,将
一个子图集合放入一个单独的图片文件中,并blit你想要使用的部分。

[mw_shl_code=applescript,true]                screen.Blit(nil, back_ground, nil)
                for i := 0; i < 3; i++ {
                        for j := 0; j < 3; j++ {
                                if logic_plane[j] == 1 {
                                        screen.Blit(&sdl.Rect{int16(i*200 + 10), int16(j*200 + 10), 180, 180},
                                                ox, &sdl.Rect{0, 0, 170, 170})
                                } else if logic_plane[j] == 2 {
                                        screen.Blit(&sdl.Rect{int16(i*200 + 10), int16(j*200 + 10), 180, 180},
                                                ox, &sdl.Rect{0, 200, 170, 170})
                                }
                        }
                }
                screen.Flip()
        }
}[/mw_shl_code]
首先我们将背景贴到屏幕上。
我们知道方法Blit中,调用者是目标界面,第二个参数是源界面,那么第一个参数和第三个参数是干什么的呢?
这两个参数是接受一个sdl.Rect结构,第一个参数表示将要贴在目标界面的哪个部分,第三个参数表示取自源界面的哪个部分。这样就完成了精灵图的操作了。
每次只要根据图片选择一定矩形区域内的图片,就可以部分显示了。。

至于其实最后还应该写一下胜利逻辑。。。由于跟SDL就没什么关系了。。。所以也就懒得写了。。。。

效果图

井字游戏2.png
井字游戏1.png
全部源码:
[mw_shl_code=applescript,true]package main

import (
        "github.com/banthar/Go-SDL/sdl"
)

func main() {
        var back_ground, ox, screen *sdl.Surface
        logic_plane := [3][3]int{}
        running := true
        turn := true
        sdl.Init(sdl.INIT_EVERYTHING)
        defer sdl.Quit()
        screen = sdl.SetVideoMode(600, 600, 32, sdl.SWSURFACE)
        back_ground = sdl.Load("back_ground.png")
        ox = sdl.Load("ox.png")
        defer back_ground.Free()
        defer ox.Free()
        sdl.WM_SetCaption("井字游戏", "")
        for running {
                event := sdl.PollEvent()
                switch e := event.(type) {
                //switch a.(type)检查接口a的类型,然后e就相当于转换了接口的类型
                case *sdl.QuitEvent:
                        running = false
                        return
                case *sdl.MouseButtonEvent:
                        if e.Type == sdl.MOUSEBUTTONDOWN {
                                switch e.Button {
                                case sdl.BUTTON_RIGHT:
                                        for i := 0; i < 3; i++ {
                                                for j := 0; j < 3; j++ {
                                                        logic_plane[j] = 0
                                                }
                                        }
                                case sdl.BUTTON_LEFT:
                                        i := e.X / 200
                                        j := e.Y / 200
                                        if logic_plane[j] == 0 {
                                                if turn {
                                                        turn = !turn
                                                        logic_plane[j] = 1
                                                } else {
                                                        turn = !turn
                                                        logic_plane[j] = 2
                                                }
                                        }
                                }
                        }
                }
                screen.Blit(nil, back_ground, nil)
                for i := 0; i < 3; i++ {
                        for j := 0; j < 3; j++ {
                                if logic_plane[j] == 1 {
                                        screen.Blit(&sdl.Rect{int16(i*200 + 10), int16(j*200 + 10), 180, 180},
                                                ox, &sdl.Rect{0, 0, 170, 170})
                                } else if logic_plane[j] == 2 {
                                        screen.Blit(&sdl.Rect{int16(i*200 + 10), int16(j*200 + 10), 180, 180},
                                                ox, &sdl.Rect{0, 200, 170, 170})
                                }
                        }
                }
                screen.Flip()
        }
}
[/mw_shl_code]

————————————————————————————————————————————————————————————————————————
越写到后面越累啊。。。。最后就懒得说话了。。。。
下次应该就是打砖块了。。。。不过应该就分很多期写了。。。一起说起来太麻烦。。。

反应不好。。不爽求发糖@Whisper1166 @Mr_Alex

评分

参与人数 2宅魂 +1 宅币 +31 贡献 +1 元气(技能点) +2 活跃 +1 收起 理由
cao884203 + 1 + 1 + 1 Σ( ° △ °|||)︴ 碉堡了
Mr_Alex + 30 + 1 + 2 Σ( ° △ °|||)︴ 碉堡了

查看全部评分

等死星人
回复

使用道具 举报

该用户从未签到

12

主题

54

好友

1万

积分

喵星人

这里是❤犯二傲娇吃货卖萌晓受受❤喵~o(≧v≦)o~

积分
14552
发表于 2013-4-2 02:24:00 | 显示全部楼层
_(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)_【看到大师后吓到尸横遍野】
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

30

主题

127

好友

2万

积分

技术宅认证程序员

重度中二患者

积分
28325
 楼主| 发表于 2013-4-2 12:04:32 | 显示全部楼层
晓晓酱 发表于 2013-4-2 02:24
_(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)_【看到大师后吓到尸横遍野】 ...

只是写很简单的东西吧。。。。
我才是尸横遍野啊!
等死星人
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

37

好友

1万

积分

第一章

积分
11825
发表于 2013-4-2 12:34:02 | 显示全部楼层
支持下go语言,虽然我还没用过
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

54

好友

1万

积分

喵星人

这里是❤犯二傲娇吃货卖萌晓受受❤喵~o(≧v≦)o~

积分
14552
发表于 2013-4-2 16:25:57 | 显示全部楼层
foodszhu 发表于 2013-4-2 12:04
只是写很简单的东西吧。。。。
我才是尸横遍野啊!

可能是因为我太渣了_(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)__(:3」∠)_
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

9

主题

34

好友

4626

积分

序章

积分
4626
发表于 2013-4-2 16:41:03 | 显示全部楼层
这个IDE是什么啊,看上去很不错啊
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

30

主题

127

好友

2万

积分

技术宅认证程序员

重度中二患者

积分
28325
 楼主| 发表于 2013-4-2 16:45:53 | 显示全部楼层
langyxxl 发表于 2013-4-2 16:41
这个IDE是什么啊,看上去很不错啊

sublime text。。。。一款非常不错的文本编辑器。。。但不是IDE。。。不过配置配置可以达到IDE的效果的说
虽然说更喜欢vim,但是vim的配色实在比不上这个。。。
等死星人
回复 支持 反对

使用道具 举报

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

21

主题

63

好友

1万

积分

第一章

积分
18553
发表于 2013-4-2 16:49:55 | 显示全部楼层
嗯 嗯  晚上回去再看代码
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

30

主题

127

好友

2万

积分

技术宅认证程序员

重度中二患者

积分
28325
 楼主| 发表于 2013-4-2 16:51:53 | 显示全部楼层
moxiagy 发表于 2013-4-2 16:49
嗯 嗯  晚上回去再看代码

写的非常丑。。。。捂脸。。。求轻喷。。。
等死星人
回复 支持 反对

使用道具 举报

本版积分规则

小黑屋|手机版|技术宅(Z站|基宅) ( 粤ICP备18082987号-1 )

GMT+8, 2025-7-2 00:06 , Processed in 0.134127 second(s), 28 queries , Redis On.

Copyright © 2018 技术宅社区

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表