我的《超級馬里奧》我做主:會漂移掉頭帶剎車音效,C++從零打造
代碼已開源
你見過這樣的超級馬里奧嗎?
跑著跑著突然停下來個帥氣掉頭,還自帶剎車音效:
“踩”扁“板栗仔”(goomba)時直接“變酷”(得到一副墨鏡):
這,就是一位油管博主用C++和SFML自己從頭制作的紅白機版超級馬里奧。
C++不用介紹,SFML想必有很多人也熟悉,就是一個用來簡化寫小游戲或者多媒體應用程序的API,包括系統,窗口,圖形,音頻和網絡五大模塊。
你也可以自己做一個~
由于畫面看起來實在太逼真,有人甚至提醒博主:小心“版權狂魔”任天堂來找你哦!
心動么?
你也可以自己做一個~
話不多說,來看教程。
手把手教你用C++打造超級馬里奧
一共分為4大塊。
1、基本控制
設置游戲窗口大小為256×240。
我們先自己繪制一個留胡子的小伙子——馬里奧。
通過函數將它載入程序。
Mario::Mario() :
x(0.5f * SCREEN_WIDTH),
y(0.5f * SCREEN_HEIGHT)
{
texture.loadFromFile("Resources/Images/Mario.png");
sprite.setTexture(texture);
}
void Mario::draw(sf: :RenderWindow& i_window)
{
sprite.setPosition(round(x), round(y));
i_window.draw(sprite);
}
得到這樣的界面:
然后處理地圖,由于地圖的寬度不同,將它存儲為數組向量。
typedef std::vector<std::array<Cel1, SCREEN_HEIGHT / CELL_SIZE>> Map;
sf::Texture map_texture;
map_texture.1oadFromFile("Resources/Images/Map.png");
Map map(SCREEN_WIDTH/CELL_SIZE);
Mario mario;
for(unsigned short a = θ; a < map.size(); a++)
{
for (unsigned short b = map[a].size() - 2;b< map[a].size(); b++)
{
map[a][b] = Cell: :Wa1l;
{
}
現在畫面是這樣的:
接著開始集中打造馬里奧。
先讓他能動起來,前進后退:
并且獲得重力:
void Mario::update()
{
if (1 == sf::Keyboard: :isKeyPressed(sf: :Keyboard: :Left))
{
x-=MARIO_SPEED;
}
else if (1 == sf::Keyboard::isKeyPressed(sf: :Keyboard: :Right))
{
x+= MARIO_SPEED;
}
vertical_speed += GRAVITY;
y += vertical_speed;
}
有了,但得讓馬里奧落到地上。
那就獲取一下馬里奧的坐標,用下面這些公式檢查與之相交的所有單元格:
成功:
但是不能讓馬里奧跑出地圖:
void Mario::update(const Map& i_map)
{
if (1 == sf::Keyboard::isKeyPressed(sf: :Keyboard: :Left))
{
x = std::max<float>(x - MARIO_SPEED,θ);
}
else if (1 == sf::Keyboard: :isKeyPressed(sf: :Keyboard: :Right))
{
x=std::min<float>(MARIO_SPEED + x,CELL_SIZE *(i_map.size() - 1));
}
}
接下來添加碰撞。
用二進制表示馬里奧碰到的單元格,用一個地圖碰撞函數檢查并返回0000-1111這15種可能,然后使用位運算檢查方向。
成功:
接下來,看看它能不能跳過這個墻。
顯然不行……
搞起來,其中,為了使馬里奧的跳躍高度和我們按住鍵盤的時長為正比,需要創建一個跳躍計時器變量。
if (1 == sf: :Keyboard: :isKeyPressed(sf: :Keyboard: :Up))
{
if (θ == vertical_speed && θ < map_collision(x, 1 + y, Cell::Wa1l, i_map))
{
vertical_speed = MARIO_JUMP_SPEED;
jump_timer = MARIO_JUMP_TIMER;
}
else if (θ < jump_timer)
{
vertical_speed = MARIO_JUMP_SPEED;
jump_timer--;
}
else
{
vertical_speed = std::min<float>(GRAVITY + vertical_speed, MAX_VERTICAL_SPEED);
}
}
再來挑戰一下:
完美。
最后,給它添加加速度和摩擦力,也就是我們在文章一開頭看到的那種剎車特效。
if (1 == sf::Keyboard: :isKeyPressed(sf: :Keyboard: :Left))
{
horizontal_speed=std::max(horizontal_speed-MARIO_ACCELERATION,-MARIO_WALK_SPEED);
}
else if (1 == sf: :Keyboard::isKeyPressed(sf::Keyboard::Right))
{
horizontal_speed =std::min(MARIO_ACCELERATION +horizontal_speed,MARIO_WALK_SPEED);
}
else if (θ < horizontal_speed)
{
horizontal_speed-=MARIO_ACCELERATION;
}
else if (θ> horizontal_speed)
{
horizontal_speed+=MARIO_ACCELERATION;
}
至此,基本控制就完成了,進入地圖繪制部分。
2、地圖
將地圖存為圖片之前,需分為兩部分,上部分存為磚塊,下部分存為實體。
使用一個新函數將圖像轉為map。
Map convert_sketch(const sf::Image& i_map_sketch, Mario& i_mario)
修改drawback函數獲得磚塊像素顏色,繪制磚塊。再畫點云朵,基礎地圖就好了。
接下來就是挨個繪制剩余元素了。
if (sf::Color(109,255,85)==pixel)//Flagpole
{
sprite_x=12;
if (sf::Color(109,255,85) == pixel_up)
{
sprite_y=1
}
}
成果如下:
什么?缺個城堡?作者表示:累了,隨便吧……
接下來,使用下面這個公式,讓界面跟著馬里奧前進后退。
short view_x = std::clamp<int>(mario.get_x()+0.5f *(CELL_SIZE - SCREEN_WIDTH),θ,CELL_SIZE*n)
地圖搞定,上板栗仔!
3、板栗仔
板栗仔的行動和馬里奧相似,代碼可以基本復制。不同的是一旦它們碰到東西就會改變方向。
如何讓板栗仔出現?
當馬里奧靠近它們時,更新地圖。
void Goomba::draw(unsigned 1_view_x, sf::RenderWindow& i_window)
{
if (-CELL_SIZE < round(y) && round(x) > static_cast<int>(i_view_x) - CELL_SIZE && round(x)
{
sprite.setTexture(texture);
sprite.setPosition(round(x),round(y));
i_window.draw(sprite);
}
}
if(0 ==death_timer)
{
vertical_speed =std::min(GRAVITY + vertical_speed, MAX_VERTICAL_SPEED);
y+= vertical_speed;
}
else if (1 == death_timer)
{
vertical_speed = MARIO_JUMP_SPEED;
}
death_timer = std::max(0, death_timer - 1);
經歷過n個bug后,終于沒問題。
到了最后一部分了。
4、優化
這部分主要就是做做代碼優化,根據自己喜好改變一些原作風格什么的。
比如重新繪制一個馬里奧,并分成三種狀態:暫停、行走、跳躍以及die。
終于,全部搞定?。?/p>
寫一個切換狀態函數進行控制。
void Animation::update()
{
animation_iterator++;
while (animation_iterator >= animation_speed)
{
animation_iterator -= animation_speed;
current_frame = (1 + current_frame)% total_frames;
}
}
終于,全部搞定??!
怎么樣?還挺成功吧?
過程其實也不乏挑戰,有網友就表示:我以為很簡單,直到我看到了代碼。
而現在你是不是也對背后的作者產生了一絲好奇?
下面就來認識一下。
作者介紹
這位博主叫Kofybrek,今年6月剛剛成為一名YouTuber,目前已有1000粉絲。
他用C++做了很多小游戲:包括掃雷、俄羅斯方塊、吃豆人等等。
也搞機器學習,比如教AI玩Flappy Bird。
從他的座右銘“I do programming for fun”,可以看出小哥是很喜歡用編程做一些好玩的東西了,可以期待他更多的作品。
最后,如果你想試試親手打造這樣一個馬里奧,可以戳下面的鏈接。
代碼:
https://github.com/Kofybrek/Super-Mario-Bros
教程視頻:
https://www.youtube.com/watch?v=Kfc2W9EOHRk
- 北大開源最強aiXcoder-7B代碼大模型!聚焦真實開發場景,專為企業私有部署設計2024-04-09
- 剛剛,圖靈獎揭曉!史上首位數學和計算機最高獎“雙料王”出現了2024-04-10
- 8.3K Stars!《多模態大語言模型綜述》重大升級2024-04-10
- 谷歌最強大模型免費開放了!長音頻理解功能獨一份,100萬上下文敞開用2024-04-10




