?[導(dǎo)讀]本系列博文內(nèi)容鏈接如下:
【C++】做一個飛機空戰(zhàn)小游戲(一)——使用getch()函數(shù)獲得鍵盤碼值
【C++】做一個飛機空戰(zhàn)小游戲(二)——利用getch()函數(shù)實現(xiàn)鍵盤控制單個字符移動
【C++】做一個飛機空戰(zhàn)小游戲(三)——getch()函數(shù)控制任意造型飛機圖標(biāo)移動【C++】做一個飛機空戰(zhàn)小游戲(四)——給游戲添加背景音樂(多線程技巧應(yīng)用)
【C++】做一個飛機空戰(zhàn)小游戲(五)——getch()控制兩個飛機圖標(biāo)移動(控制光標(biāo)位置)
【C++】做一個飛機空戰(zhàn)小游戲(六)——給兩架飛機設(shè)置不同顏色(cout輸出彩色字符、結(jié)構(gòu)體使用技巧)
【C++】做一個飛機空戰(zhàn)小游戲(七)——兩組按鍵同時檢測平滑移動(GetAsyncKeyState()函數(shù)應(yīng)用)
【C++】做一個飛機空戰(zhàn)小游戲(八)——生成敵方炮彈(rand()函數(shù)應(yīng)用)
【C++】做一個飛機空戰(zhàn)小游戲(九)——發(fā)射子彈的編程技巧
【C++】做一個飛機空戰(zhàn)小游戲(十)——子彈擊落炮彈、炮彈與飛機相撞?
在【C++】做一個飛機空戰(zhàn)小游戲(一)——使用getch()函數(shù)獲得鍵盤碼值一文中介紹了如何利用getch()獲得鍵盤碼和各個鍵盤符號的碼值。
今天繼續(xù)介紹,利用wsad鍵和方向鍵兩種方式,實現(xiàn)控制單個字符的移動。
目錄
一、第一個小坑
二、通過wsad按鍵控制單個字符的移動
(一)字符移動的原理
1、左右移動
2、上下移動
(二)清空屏幕函數(shù)和頭文件
(三)程序代碼
1、清屏
2、再調(diào)用show_plane()重新顯示字符
3、檢測按鍵碼值,計算字符坐標(biāo)值
三、通過方向按鍵控制單個字符的移動
(一)雙碼按鍵獲取碼值的方法
(二)實現(xiàn)代碼
四、第二個小坑
一、第一個小坑
寫程序要循序漸進,先實現(xiàn)最基本的功能,再不斷深化。所以,要先編寫一個簡單程序測試一下getch()函數(shù),在鍵盤上按下代表不同方向的按鍵,然后根據(jù)不同的按鍵,在屏幕上輸出相應(yīng)的方向信息,模擬控制字符移動的方向。程序的具體目的是:當(dāng)按'w'鍵,屏幕輸出"up";當(dāng)按's'鍵,屏幕輸出"down";當(dāng)按'a'鍵,屏幕輸出"left";當(dāng)輸入'd'鍵,屏幕輸出"right"。
根據(jù)以上想法,編寫程序代碼如下:
#include <iostream>
#include "conio.h"
using namespace std;
int main()
{
while(1) //循環(huán)等待輸入字符
{
if(getch()==119) //如果輸入字符'w'
{
cout<<"up"<<endl; //輸出字符串"up"
}
else if(getch()==115) //如果輸入字符's'
{
cout<<"down"<<endl; //輸出字符串"down"
}
else if(getch()==97) //如果輸入字符'a'
{
cout<<"left"<<endl; //輸出字符串"left"
}
else if(getch()==100) //如果輸入字符'd'
{
cout<<"right"<<endl;//輸出字符串"right"
}
else //如果輸入其他字符
{
; //無響應(yīng)
}
}
return 0;
}
先簡單測試一下基本的功能,結(jié)果發(fā)現(xiàn)一些問題:當(dāng)每輸入一次字符'w'時,屏幕顯示一次"up",這個按鍵是正常的。
但是當(dāng)測試其他三個字符時,卻出現(xiàn)了異常:輸入字符's'時,需要按兩次鍵盤才顯示一次"down";需要輸入3次'a',才顯示一次"left",需要輸入4次'd',才顯示一次"right"。
up //按1次'w'
down //按2次's'
left //按3次'a'
right //按4次'd'
本程序并沒有完全實現(xiàn)按一次鍵盤就執(zhí)行一次相應(yīng)動作的目的。那么問題出在哪里了呢?
經(jīng)過分析發(fā)現(xiàn),程序當(dāng)中if語句的前4個分支,其判定條件都是直接調(diào)用了getch()函數(shù),而if語句執(zhí)行的順序是從第一個開始依次判定,當(dāng)找到判定條件為真的那一個if分支時才跳出整個if語句。那么也就是說,無論按下了哪個按鍵,程序都需要從第一個if語句分支開始依次進行檢測和判斷,每一個分支都需要調(diào)用一次getch(),而每次調(diào)用getch()都需要有按鍵按下才能觸發(fā)。所以,在第一個分支中的字符'a',按一次就能觸發(fā),而在第二個分支中的字符's',需要按2次才能觸發(fā),在第三個分支中的字符'a'需要按3次觸發(fā),在第四個分支的'd'需要按4次。
問題分析清楚了,那么怎么解決呢?解決的方案就是另外聲明一個變量"key_value",用來存放每次按下按鍵利用getch()的值,然后在4個if分支中判斷key_value的值是否與4個字符的碼值相等。調(diào)整后的程序如下圖所示。
#include <iostream>
#include "conio.h"
using namespace std;
int main()
{
int key_value; //聲明存放按鍵碼值的變量
while(1) //循環(huán)等待輸入字符
{
key_value=getch(); //獲取按鍵碼值
if(key_value==119) //如果輸入字符'w'
{
cout<<"up"<<endl; //輸出字符串"up"
}
else if(key_value==115) //如果輸入字符's'
{
cout<<"down"<<endl; //輸出字符串"down"
}
else if(key_value==97) //如果輸入字符'a'
{
cout<<"left"<<endl; //輸出字符串"left"
}
else if(key_value==100) //如果輸入字符'd'
{
cout<<"right"<<endl;//輸出字符串"right"
}
else //如果輸入其他字符
{
; //無響應(yīng)
}
}
return 0;
}
再對以上程序進行測試,發(fā)現(xiàn)運行正常了,4個字符都只需按1次即可輸出相應(yīng)字段了。
up //按1次'w'
down //按1次's'
left //按1次'a'
right //按1次'd'
二、通過wsad按鍵控制單個字符的移動
測試完按鍵控制的基本程序后,就需要繼續(xù)編寫程序,實現(xiàn)通過按鍵來控制圖標(biāo)進行移動的目標(biāo)了,我們還是由最簡單的情形開始——圖標(biāo)只由一個特殊字符'■'組成。
(一)字符移動的原理
字符移動的原理就是當(dāng)按鍵按下后,根據(jù)按鍵的碼值,分辨出要移動的意圖,計算出字符的新位置(用行號和列號的坐標(biāo)對來表示位置),然后將屏幕清空,再在新位置上重新顯示字符。這樣就完成了圖標(biāo)的移動。
1、左右移動
左右移動是通過在字符前增加或者減少空格的數(shù)量來實現(xiàn)的。增加空格數(shù)量,則字符向右移動,減少空格的數(shù)量則向左移動。
2、上下移動
上下移動是通過增加或減少字符所在行的上一行的換行符數(shù)量來實現(xiàn)的,增加換行符數(shù)量則字符向下移動,減少換行符的數(shù)量則字符向上移動。
(二)清空屏幕函數(shù)和頭文件
清屏函數(shù):system("cls")
所需頭文件:windows.h
(三)程序代碼
程序代碼預(yù)先自定義了字符定位顯示函數(shù)show_plane(),函數(shù)有兩個參量x,y,代表字符列號和行號。在主函數(shù)while(1)中,循環(huán)進行以下操作:
1、清屏
2、再調(diào)用show_plane()重新顯示字符
3、檢測按鍵碼值,計算字符坐標(biāo)值
本例通過單碼按鍵來進行控制字符移動。檢測是否有按鍵按下,如果'w'鍵按下,y值減1;如果's'鍵按下,y值加1;如果'a'鍵按下,x值減1;如果'd'鍵按下,x值加1。
完整代碼如下所示。
#include <iostream>
#include "conio.h"
using namespace std;
void show_plane(int x,int y) //預(yù)先定義字符定位顯示函數(shù),x是列坐標(biāo),y是行坐標(biāo),原點(x=0,y=0)位于屏幕左上角
{
int i,j;
system("cls"); //清屏
for(j=0;j<y;j++) //輸出y個換行符
{
cout<<endl;
}
for(i=0;i<x;i++) //輸出x個空格
{
cout<<" ";
}
cout<<"■"; //輸出要顯示的字符
}
int main()
{
int key_value; //聲明存放按鍵碼值的變量
int x=0,y=0; //聲明字符坐標(biāo),x代表列值,y代表行值
while(1) //循環(huán)等待輸入字符
{
show_plane(x,y); //重新打印字符
key_value=getch(); //獲取按鍵碼值
if(key_value==119) //如果輸入字符'w'
{
y--; //字符上移一行,行值y減1
if(y<0) //限定y值最小值為0
{
y=0;
}
}
else if(key_value==115) //如果輸入字符's'
{
y++; //字符下移一行,行值y加1
if(y>30) //限定y最大值為30
{
y=30;
}
}
else if(key_value==97) //如果輸入字符'a'
{
x--; //字符左移一列,列值x減1
if(x<0)
{
x=0; //限定x最小值為0
}
}
else if(key_value==100) //如果輸入字符'd'
{
x++; //字符右移一列,列值x加1
if(x>60)
{
x=60; //限定x最大值為60
}
}
else //如果輸入其他字符
{
; //無響應(yīng)
}
}
return 0;
}
三、通過方向按鍵控制單個字符的移動
以上介紹了使用四個單碼按鍵'w'、's'、'a'、'd'來控制字符移動,下邊再介紹一下,如何利用雙碼按鍵↑、↓、←、→來進行控制。
(一)雙碼按鍵獲取碼值的方法
雙碼按鍵和單碼按鍵的控制方法只再獲取鍵碼的時候有一點區(qū)別,其他地方完全一樣。雙碼按鍵的碼值有兩部分,需要調(diào)用兩次getch()函數(shù)來分別獲取。
單碼按鍵獲取碼值的代碼:
key_value=getch(); //獲取按鍵碼值
雙碼按鍵獲取碼值的代碼:
key_value1=getch(); //獲取按鍵碼值1
key_value2=getch(); //獲取按鍵碼值2
(二)實現(xiàn)代碼
#include <iostream>
#include "conio.h"
using namespace std;
void show_plane(int x,int y) //預(yù)先定義字符定位顯示函數(shù),x是列坐標(biāo),y是行坐標(biāo),原點(x=0,y=0)位于屏幕左上角
{
int i,j;
system("cls"); //清屏
for(j=0;j<y;j++) //輸出y個換行符
{
cout<<endl;
}
for(i=0;i<x;i++) //輸出x個空格
{
cout<<" ";
}
cout<<"■"; //輸出要顯示的字符
}
int main()
{
int key_value1,key_value2; //聲明存放按鍵碼值的兩個變量
int x=0,y=0; //聲明字符坐標(biāo),x代表列值,y代表行值
while(1) //循環(huán)等待輸入字符
{
show_plane(x,y); //重新打印字符
key_value1=getch(); //獲取按鍵碼值1
key_value2=getch(); //獲取按鍵碼值2
if(key_value1==224 && key_value2==72)//如果輸入字符'↑'
{
y--; //字符上移一行,行值y減1
if(y<0) //限定y值最小值為0
{
y=0;
}
}
else if(key_value1==224 && key_value2==80)//如果輸入字符'↓'
{
y++; //字符下移一行,行值y加1
if(y>30) //限定y最大值為30
{
y=30;
}
}
else if(key_value1==224 && key_value2==75) //如果輸入字符'←'
{
x--; //字符左移一列,列值x減1
if(x<0)
{
x=0; //限定x最小值為0
}
}
else if(key_value1==224 && key_value2==77) //如果輸入字符'→'
{
x++; //字符右移一列,列值x加1
if(x>60)
{
x=60; //限定x最大值為60
}
}
else //如果輸入其他字符
{
; //無響應(yīng)
}
}
return 0;
}
四、第二個小坑
以上兩種控制字符移動的代碼經(jīng)測試,對于單碼按鍵程序來說,如果不小心按了其他單碼按鍵或者雙碼按鍵,對控制是沒有影響的??墒菍τ陔p碼按鍵程序來說,如果不小心按了一次單碼按鍵,再按雙碼按鍵進行控制,發(fā)現(xiàn)無論按哪個控制鍵,無論按多少次,圖標(biāo)都不再移動了。
這是因為,假如按了一次單碼鍵,key_value1獲得了碼值,但是key_value2沒有獲得碼值,再次按雙碼鍵時,會把第一個碼值賦值給了上一個key_value2,第二個碼值賦值給了當(dāng)前的key_value1,而當(dāng)前的key_value2又未重新賦值,還保持原來的值不變。這就相當(dāng)于每次按下雙碼鍵,獲得的key_value1和key_value正好是相反的。因此控制程序才失效了。
也就是如果游戲再做得復(fù)雜些,要同時用到單碼按鍵和雙碼按鍵,程序就會出問題,所以程序必須區(qū)分出是單碼鍵按下還是雙碼鍵按下,然后確定出是哪個命令鍵按下了。文章來源:http://www.zghlxwxcb.cn/news/detail-611611.html
經(jīng)優(yōu)化調(diào)整后的最終程序如下所示:文章來源地址http://www.zghlxwxcb.cn/news/detail-611611.html
#include <iostream>
#include "conio.h"
using namespace std;
void show_plane(int x,int y) //預(yù)先定義字符定位顯示函數(shù),x是列坐標(biāo),y是行坐標(biāo),原點(x=0,y=0)位于屏幕左上角
{
int i,j;
system("cls"); //清屏
for(j=0;j<y;j++) //輸出y個換行符
{
cout<<endl;
}
for(i=0;i<x;i++) //輸出x個空格
{
cout<<" ";
}
cout<<"■"; //輸出要顯示的字符
}
int main()
{
int key_value1,key_value2; //聲明存放按鍵碼值的兩個變量
bool up_btn_press=false,down_btn_press=false,left_btn_press=false,right_btn_press=false;//四個方向鍵是否按下標(biāo)志,按下為true,未按下為false
int x=0,y=0; //聲明字符坐標(biāo),x代表列值,y代表行值
while(1) //循環(huán)等待輸入字符
{
show_plane(x,y); //重新打印字符
key_value1=getch(); //獲取按鍵碼值1
if(key_value1==224)
{
key_value2=getch();
switch(key_value2)
{
case 72:
up_btn_press=true; //置↑按下 標(biāo)志
break;
case 80:
down_btn_press=true;//置↓按下 標(biāo)志
break;
case 75:
left_btn_press=true;//置←按下 標(biāo)志
break;
case 77:
right_btn_press=true;//置→按下 標(biāo)志
break;
}
}
if(up_btn_press)//如果輸入字符'↑'
{
y--; //字符上移一行,行值y減1
if(y<0) //限定y值最小值為0
{
y=0;
}
up_btn_press=false;
}
else if(down_btn_press)//如果輸入字符'↓'
{
y++; //字符下移一行,行值y加1
if(y>30) //限定y最大值為30
{
y=30;
}
down_btn_press=false;
}
else if(left_btn_press) //如果輸入字符'←'
{
x--; //字符左移一列,列值x減1
if(x<0)
{
x=0; //限定x最小值為0
}
left_btn_press=false;
}
else if(right_btn_press) //如果輸入字符'→'
{
x++; //字符右移一列,列值x加1
if(x>60)
{
x=60; //限定x最大值為60
}
right_btn_press=false;
}
else //如果輸入其他字符
{
; //無響應(yīng)
}
}
return 0;
}
到了這里,關(guān)于【C++】做一個飛機空戰(zhàn)小游戲(二)——利用getch()函數(shù)實現(xiàn)鍵盤控制單個字符移動的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!