ページ 1 / 1
マリオ風のジャンプについて
Posted: 2012年8月19日(日) 23:29
by ボラ天神
私は今DxライブラリとC言語を使ってマリオ風のアクションゲームを作っています。
作成手順として背景の表示、移動、加速、減速、ジャンプ、とやってきたのですが、マリオみたく長くボタンを押すと大きくジャンプするみたいなことができません。
色々なサイトのコードを参考にさせてもらっていて頑張ってみたのですが、そのジャンプの処理は実装することができませんでした。
C言語は少し前から授業で触った程度です。Dxライブラリも同時期に使い始めました。
どのようにしたら私が望んでいるようにできるのか教えていただけると助かります。
コード:
#include "DxLib.h"
int count=0;
char Key[256];
void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);
struct Chara {
double x;
double y;
int g;
double spdX;
double spdY;
};
struct Chara mario;
int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return(-1);
SetDrawScreen(DX_SCREEN_BACK);
mario.x = (double)0;
mario.y = (double)32;//480 - 32 * 2;
mario.g = LoadGraph("media\\test001.png");
mario.spdX = (double)0;
mario.spdY = (double)0;
while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
ClsDrawScreen();
int Bg_flag = 0;
int count_flag = 0;
int grav = 10;
int Buf[256];
GetKeyInput(Buf);
if(Bg_flag == 0){
DrawBox(0,0,640,480,GetColor(105,122,243),TRUE); //背景を水色に1 - 1
Bg_flag = 1;
}
fps();
count++;
//-------------------------------------------------------------------------
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
mario.y -= mario.spdY;
mario.spdY -= 1;
if(mario.x < 0) mario.x = 0;
//if(mario.x > 640 - 32) mario.x = 640 - 32;
if((CheckHitKey(KEY_INPUT_Z))) {
if(mario.spdX > 8.0) mario.spdX = 8.0;
if(mario.spdX < -8.0) mario.spdX = -8.0;
}else {
if(mario.spdX > 5.0) mario.spdX = 5.0;
if(mario.spdX < -5.0) mario.spdX = -5.0;
}
if(count_flag > 1) {count_flag = 0; mario.spdX = 0;}
if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0;}
if(mario.spdY > 30.0) mario.spdY = 30.0;
if(((CheckHitKey(KEY_INPUT_C)) == TRUE && mario.y == 480 -32) && (Buf[KEY_INPUT_C] > 0 && Buf[KEY_INPUT_C] < 10)) {
mario.spdY = 15;
}else if((CheckHitKey(KEY_INPUT_C)) == TRUE && mario.y == 480 -32 && (Buf[KEY_INPUT_C] >= 10)) {
mario.spdY = 20;
}
DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);
//-------------------------------------------------------------------------
ScreenFlip();
wait_fanc();
}
DxLib_End();
return(0);
}
void wait_fanc(){
int term;
static int t=0;
term = GetNowCount()-t;
if(16-term>0)
Sleep(16-term);
t=GetNowCount();
return;
}
void fps(){
int i;
static int t=0,ave=0,f[60];
f[count%60]=GetNowCount()-t;
t=GetNowCount();
if(count%60==59){
ave=0;
for(i=0;i<60;i++)
ave+=f[i];
ave/=60;
}
if(ave!=0){
DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
DrawFormatString(0,20,GetColor(0,0,0),"%dms" ,ave);
}
return;
}
void GetKeyInput( int *KeyBuf ){
char damy[256];
GetHitKeyStateAll( damy ) ;
for( int i=0 ; i<256 ; i++ ){
if( damy[i] == 1 )
KeyBuf[i]++;
else
KeyBuf[i] = 0;
}
}
コード汚くて本当にすみません。
Re: マリオ風のジャンプについて
Posted: 2012年8月19日(日) 23:51
by ボラ天神
追伸:キーボードの右と左を同時に押すとおかしな挙動をするのも気になるので教えていただけると助かります。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 00:42
by softya(ソフト屋)
ジャンプに関しては完全に検証してませんが、構造体にJumpCountを追加して初期化。
そのあとの処理は、こんな感じです。
コード:
if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
if(mario.spdY > 30.0) mario.spdY = 30.0;
if( mario.JumpCount == 0 ) {
if( Buf[KEY_INPUT_C] > 0 ) {
mario.JumpCount++;
}
} else {
if( Buf[KEY_INPUT_C] > mario.JumpCount ) {
if( mario.JumpCount == 10 ) {
mario.spdY = 20;
} else if( mario.JumpCount < 10 ) {
mario.spdY = 15;
}
}
mario.JumpCount++;
}
左右キーの同時押しは、同時に押され倒されていない時のみの右キーとキー左の処理を書いてください。同時に押されたら押されていないと同じ扱いに成るようにします。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 00:55
by ボラ天神
>> softya(ソフト屋) さん
ありがとうございます!!
今組み込んでみたいと思います!!
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 01:12
by ボラ天神
ジャンプは一応成功しましたがやはりプログラムの順番的に
コード:
if( Buf[KEY_INPUT_C] > mario.JumpCount) {
if(mario.JumpCount == 10) {
mario.spdY = 15;
}else if(mario.JumpCount < 10) {
mario.spdY = 10;
}
}
Cボタンを押し続けると10を代入してから15を代入する形になるので長押しした場合スムーズにジャンプせずにグイン・グインと二段階に分かれてジャンプしてしまいます。
これはどうしようもないことなのでしょうか?
それと左右の挙動についてですが変更してみたのですがもちろん動きませんでしたw
自分でもおかしいと思いながら直したのですがどこが間違ってるのでしょうか?
コード:
if(CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0){
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
}
if(CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0){
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
}
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 01:13
by ボラ天神
すみません/コードで閉じるの忘れてました!!
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 10:57
by nil
10か15に統一すればいいです
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 11:00
by softya(ソフト屋)
涼雅 さんが書きました:10か15に統一すればいいです
10から15の間を計算で求めて多段階に分解するって方法もありますね。
【追記】気持ちよくなるポイントを色々調整する必要があります。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 12:57
by softya(ソフト屋)
左右の問題について
if(CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0){
だとif条件がRIGHTがOFFでかつLEFTがOFFの時にしか成立しないので、この中のif文でRIGHTがONか聞いても無駄です。
私が書いたのは、「左右が同時に押されたら押されていないと同じ扱いに成るようにします。」なので、
CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0
と
CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1
の時は何もしない様に素直に書くだけです。elseをうまく使ってください。
あとキーが押されていなくても動作する必要のある処理をCheckHitKeyのあるif文の中に書いてはいけません。
キーが押された時だけする処理とキーが押された後で起こる反応はかき分けてください。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 16:10
by ISLe
マリオジャンプは、跳び上がる初速は同じで、ボタンを押していないとき落下加速度が大きくなるようにするのだったかと。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 22:31
by ボラ天神
涼雅 さんが書きました:10か15に統一すればいいです
実際のマリオにできるだけ近づけたいのでISLeさんの意見を採用してみたいと思います。しかし、返信はとても為になりますし、本物のマリオに近づくための一歩だと思うのでどしどし書いていただけると本当に嬉しく思います。
あと左右の件なのですが、説明していただいていることはよくわかるのですが、経験が足りないためか、どこにその処理をいれたらいいかわかりません。試しに色々変えてみたのですがうまくいかないのでもう少し教えていただけると幸いです。
ISLe さんが書きました:マリオジャンプは、跳び上がる初速は同じで、ボタンを押していないとき落下加速度が大きくなるようにするのだったかと。
このような本物のマリオの動作について返信していただけるととてもありがたいと思います。具体的にはジャンプボタンを押したら上限は決まっていて、そこまで飛び、私たちが高く飛んでいるように見えるのは落下速度が遅くなるからなのですか?
実際に高く飛んでいるように見えたのは目の錯覚なのでしょうかww
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 22:43
by softya(ソフト屋)
ボラ天神 さんが書きました:
あと左右の件なのですが、説明していただいていることはよくわかるのですが、経験が足りないためか、どこにその処理をいれたらいいかわかりません。試しに色々変えてみたのですがうまくいかないのでもう少し教えていただけると幸いです。
こんな感じでしょうか?
条件は素直に書くのが一番です。
コード:
// 左右を押していないか同時押しは押していないのと同じ。
if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) ||
(CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1) ) {
// 左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
:
:
} else {
// 右キーの処理。移動・ダッシュ。
:
:
// 左キーの処理。移動・ダッシュ。
:
:
}
ボラ天神 さんが書きました:
ISLe さんが書きました:マリオジャンプは、跳び上がる初速は同じで、ボタンを押していないとき落下加速度が大きくなるようにするのだったかと。
このような本物のマリオの動作について返信していただけるととてもありがたいと思います。具体的にはジャンプボタンを押したら上限は決まっていて、そこまで飛び、私たちが高く飛んでいるように見えるのは落下速度が遅くなるからなのですか?
実際に高く飛んでいるように見えたのは目の錯覚なのでしょうかww
ISLeさんの方式だと上方向の速度は同じでも下方向の加速度を減らすので当然ながらジャンプ頂点は高くなります。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 22:56
by ボラ天神
コード:
#include "DxLib.h"
/* if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
if(mario.spdY > 30.0) mario.spdY = 30.0;
if( mario.JumpCount == 0 ) {
if( Buf[KEY_INPUT_C] > 0 ) {
mario.JumpCount++;
}
} else {
if( Buf[KEY_INPUT_C] > mario.JumpCount ) {
if( mario.JumpCount == 10 ) {
mario.spdY = 20;
} else if( mario.JumpCount < 10 ) {
mario.spdY = 15;
}
}
mario.JumpCount++;
}
*/
int count=0;
char Key[256];
void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);
struct Chara {
double x;
double y;
int g;
double spdX;
double spdY;
int JumpCount;
};
struct Chara mario;
int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return(-1);
SetDrawScreen(DX_SCREEN_BACK);
mario.x = (double)0;
mario.y = (double)32;//480 - 32 * 2;
mario.g = LoadGraph("media\\test001.png");
mario.spdX = (double)0;
mario.spdY = (double)0;
while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
ClsDrawScreen();
int Bg_flag = 0;
int count_flag = 0;
int grav = 10;
int Buf[256];
GetKeyInput(Buf);
if(Bg_flag == 0){
DrawBox(0,0,640,480,GetColor(105,122,243),TRUE); //背景を水色に1 - 1
Bg_flag = 1;
}
fps();
count++;
//-------------------------------------------------------------------------
/*
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
*/
if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) || (CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1) ) {
// 左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
if(mario.spdX > 0) {
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
if(mario.spdX < 0){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
} else {
// 右キーの処理。移動・ダッシュ。
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
// 左キーの処理。移動・ダッシュ。
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
}
mario.y -= mario.spdY;
mario.spdY -= 1;
if(mario.x < 0) mario.x = 0;
//if(mario.x > 640 - 32) mario.x = 640 - 32;
if((CheckHitKey(KEY_INPUT_Z))) {
if(mario.spdX > 8.0) mario.spdX = 8.0;
if(mario.spdX < -8.0) mario.spdX = -8.0;
}else {
if(mario.spdX > 5.0) mario.spdX = 5.0;
if(mario.spdX < -5.0) mario.spdX = -5.0;
}
if(count_flag > 1) {count_flag = 0; mario.spdX = 0;}
if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount = 0;}
if(mario.spdY > 30.0 ) mario.spdY = 30.0;
if( mario.JumpCount == 0) {
if( Buf[KEY_INPUT_C] > 0) {
mario.JumpCount++;
}
}else{
if( Buf[KEY_INPUT_C] > mario.JumpCount) {
if(mario.JumpCount < 10) {
mario.spdY = 10;
}else if(mario.JumpCount == 10) {
mario.spdY = 15;
}
}
mario.JumpCount++;
}
DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);
//-------------------------------------------------------------------------
ScreenFlip();
wait_fanc();
}
DxLib_End();
return(0);
}
void wait_fanc(){
int term;
static int t=0;
term = GetNowCount()-t;
if(16-term>0)
Sleep(16-term);
t=GetNowCount();
return;
}
void fps(){
int i;
static int t=0,ave=0,f[60];
f[count%60]=GetNowCount()-t;
t=GetNowCount();
if(count%60==59){
ave=0;
for(i=0;i<60;i++)
ave+=f[i];
ave/=60;
}
if(ave!=0){
DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
DrawFormatString(0,20,GetColor(0,0,0),"%dms" ,ave);
}
return;
}
void GetKeyInput( int *KeyBuf ){
char damy[256];
GetHitKeyStateAll( damy ) ;
for( int i=0 ; i<256 ; i++ ){
if( damy[i] == 1 )
KeyBuf[i]++;
else
KeyBuf[i] = 0;
}
}
これで左右の変な挙動は治りました!!!
さすがですねww
コードを素直にかつ単純に綺麗に書く事が大切ということをまた思い知らされましたw
それとジャンプについてですが、上方向にジャンプしているがジャンプした瞬間から下方向への力も働いているということですか?
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 23:17
by ISLe
ボラ天神 さんが書きました:このような本物のマリオの動作について返信していただけるととてもありがたいと思います。具体的にはジャンプボタンを押したら上限は決まっていて、そこまで飛び、私たちが高く飛んでいるように見えるのは落下速度が遅くなるからなのですか?
実際に高く飛んでいるように見えたのは目の錯覚なのでしょうかww
高さの上限ではなくて、跳び上がる強さといいましょうか。
例えば、月の重力は地球の6分の1しかないので、月面では地球よりも高く飛べるわけです。
簡単なサンプルコードを書いてみました。
アルゴリズムはとてもシンプルです。
コード:
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) return 0;
SetDrawScreen(DX_SCREEN_BACK);
const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int CHARA_W = 64;
const int CHARA_H = 64;
int x, y;
bool jumping = false;
float vy, ga;
x = (SCREEN_W-CHARA_W)/2;
y = SCREEN_H-CHARA_H;
while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
if (CheckHitKey(KEY_INPUT_C) != 0) {
if (!jumping) {
vy = -16.0f; // 初速
jumping = true;
}
ga = 0.5f; // ジャンプボタンを押しているときの落下加速度
}
else {
ga = 3.0f; // ジャンプボタンを離しているときの落下加速度
}
y += vy;
vy += ga;
if (y > SCREEN_H-CHARA_H) {
y = SCREEN_H-CHARA_H;
vy = ga = 0.0f;
jumping = false;
}
DrawBox(x, y, x+CHARA_W, y+CHARA_H, GetColor(255,255,255), TRUE);
}
DxLib_End();
return 0;
}
Cキーで白い箱がジャンプします。
ジャンプ中にキーを離しているあいだ落下速度が速くなります。
見た目にはボタンを離したところでストンと落下するように見えます。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 23:18
by softya(ソフト屋)
ボラ天神 さんが書きました:それとジャンプについてですが、上方向にジャンプしているがジャンプした瞬間から下方向への力も働いているということですか?
ご自分で毎フレーム
mario.spdY -= 1;
されてますよね?これが下方向の加速度です。
つまり、マイナスなので下方向に速度が毎フレーム1づつ増える(加速度)処理です。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 23:25
by ISLe
落下加速度をもっと小さくすると、水中ステージでマリオが手で掻いたあとゆっくり下降するのを表現できます。
つまり、ジャンプと水中の動きはパラメータが違うだけだということです。
Re: マリオ風のジャンプについて
Posted: 2012年8月20日(月) 23:38
by ボラ天神
お二人方が言っていることが分かりました!!
しかし何故かサンプルプログラムが私の環境で動きませんでした。しかしサンプルプログラムを上げていただいたおかげで更に理解を深めることができました!
内容は理解できたと思うのですが、実際に組み込んでないので今から頑張ってみたいと思います!
できたらまたあげたいと思います。
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 00:59
by ボラ天神
本当に申し訳ありません。私はわかったつもりだったのかもしれませんww
今まで組み込んでみていたのですが、やってみると難しく成功しません。
ISLeさんのサンプルコードを参考に作ってみたのですがどうもうまくいきません。
ゲームプログラミングではなく基礎C言語でつまづいている可能性もありますが、どのように組み込めばよいでしょうか?
教えていただけるととても助かります。
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 01:09
by softya(ソフト屋)
ボラ天神 さんが書きました:本当に申し訳ありません。私はわかったつもりだったのかもしれませんww
今まで組み込んでみていたのですが、やってみると難しく成功しません。
ISLeさんのサンプルコードを参考に作ってみたのですがどうもうまくいきません。
ゲームプログラミングではなく基礎C言語でつまづいている可能性もありますが、どのように組み込めばよいでしょうか?
教えていただけるととても助かります。
現状のコードを提示してください。
その方が自分で考えたものですから問題点を指摘された時の理解度が高いと思います。
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 01:21
by ボラ天神
コード:
#include "DxLib.h"
/* if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
if(mario.spdY > 30.0) mario.spdY = 30.0;
if( mario.JumpCount == 0 ) {
if( Buf[KEY_INPUT_C] > 0 ) {
mario.JumpCount++;
}
} else {
if( Buf[KEY_INPUT_C] > mario.JumpCount ) {
if( mario.JumpCount == 10 ) {
mario.spdY = 20;
} else if( mario.JumpCount < 10 ) {
mario.spdY = 15;
}
}
mario.JumpCount++;
}
*/
int count=0;
char Key[256];
void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);
struct Chara {
double x;
double y;
int g;
double spdX;
double spdY;
int JumpCount;
};
struct Chara mario;
int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return(-1);
SetDrawScreen(DX_SCREEN_BACK);
mario.x = (double)0;
mario.y = (double)32;//480 - 32 * 2;
mario.g = LoadGraph("media\\test001.png");
mario.spdX = (double)0;
mario.spdY = (double)0;
while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
ClsDrawScreen();
int Bg_flag = 0;
int count_flag = 0;
int grav = 10;
int Buf[256];
bool jumpflag = false;
double oti;
GetKeyInput(Buf);
if(Bg_flag == 0){
DrawBox(0,0,640,480,GetColor(105,122,243),TRUE); //背景を水色に1 - 1
Bg_flag = 1;
}
fps();
count++;
//-------------------------------------------------------------------------
/*
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
*/
if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) || (CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1) ) {
// 左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
if(mario.spdX > 0) {
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
if(mario.spdX < 0){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
} else {
// 右キーの処理。移動・ダッシュ。
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
// 左キーの処理。移動・ダッシュ。
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
}
if(mario.x < 0) mario.x = 0;
//if(mario.x > 640 - 32) mario.x = 640 - 32;
if((CheckHitKey(KEY_INPUT_Z))) {
if(mario.spdX > 8.0) mario.spdX = 8.0;
if(mario.spdX < -8.0) mario.spdX = -8.0;
}else {
if(mario.spdX > 5.0) mario.spdX = 5.0;
if(mario.spdX < -5.0) mario.spdX = -5.0;
}
if(count_flag > 1) {count_flag = 0; mario.spdX = 0;}
if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount = 0;}
if(mario.spdY > 30.0 ) mario.spdY = 30.0;
/*xxx:if( mario.JumpCount == 0) {
if( Buf[KEY_INPUT_C] > 0) {
mario.JumpCount++;
}
}else{
if( Buf[KEY_INPUT_C] > mario.JumpCount) {
if(mario.JumpCount < 10) {
mario.spdY = 10;
}else if(mario.JumpCount == 10) {
mario.spdY = 15;
}
}
mario.JumpCount++;
}
xxx:*/
if(KEY_INPUT_C == 1) {
if(!jumpflag) {
mario.spdY = 15;
jumpflag = true;
}
oti = 0.5;
}else{
if(!jumpflag){
oti = 3.0;
}
}
mario.y -= mario.spdY;
mario.spdY -= oti;
DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);
//-------------------------------------------------------------------------
ScreenFlip();
wait_fanc();
}
DxLib_End();
return(0);
}
void wait_fanc(){
int term;
static int t=0;
term = GetNowCount()-t;
if(16-term>0)
Sleep(16-term);
t=GetNowCount();
return;
}
void fps(){
int i;
static int t=0,ave=0,f[60];
f[count%60]=GetNowCount()-t;
t=GetNowCount();
if(count%60==59){
ave=0;
for(i=0;i<60;i++)
ave+=f[i];
ave/=60;
}
if(ave!=0){
DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
DrawFormatString(0,20,GetColor(0,0,0),"%dms" ,ave);
}
return;
}
void GetKeyInput( int *KeyBuf ){
char damy[256];
GetHitKeyStateAll( damy ) ;
for( int i=0 ; i<256 ; i++ ){
if( damy[i] == 1 )
KeyBuf[i]++;
else
KeyBuf[i] = 0;
}
}
です。
さっき消してしまって作り直したのですが、更に別な挙動になってしまいましたが、結果的におかしいです。
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 10:31
by softya(ソフト屋)
分析力を身につけるためにも、おかしい状態を出来るだけ正確・具体的に説明してくださいね。
それと、自分でで調べたほうが良いと思いますので方法を教えます。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2
まず、自分で調べてみて何処が悪かったか報告をお待ちしています。
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 22:57
by ボラ天神
コード:
#include "DxLib.h"
/* if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
if(mario.spdY > 30.0) mario.spdY = 30.0;
if( mario.JumpCount == 0 ) {
if( Buf[KEY_INPUT_C] > 0 ) {
mario.JumpCount++;
}
} else {
if( Buf[KEY_INPUT_C] > mario.JumpCount ) {
if( mario.JumpCount == 10 ) {
mario.spdY = 20;
} else if( mario.JumpCount < 10 ) {
mario.spdY = 15;
}
}
mario.JumpCount++;
}
*/
int count=0;
char Key[256];
void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);
struct Chara {
double x;
double y;
int g;
double spdX;
double spdY;
int JumpCount;
};
struct Chara mario;
int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
AllocConsole();
freopen("CONOUT$", "w",stdout);
ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return(-1);
SetDrawScreen(DX_SCREEN_BACK);
mario.x = (double)0;
mario.y = (double)32;//480 - 32 * 2;
mario.g = LoadGraph("media\\test001.png");
mario.spdX = (double)0;
mario.spdY = (double)0;
bool jumpflag = false;
while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
ClsDrawScreen();
int Bg_flag = 0;
int count_flag = 0;
int grav = 10;
int Buf[256];
double oti;
GetKeyInput(Buf);
if(Bg_flag == 0){
DrawBox(0,0,640,480,GetColor(105,122,243),TRUE); //背景を水色に1 - 1
Bg_flag = 1;
}
fps();
count++;
//-------------------------------------------------------------------------
/*
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
*/
if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) || (CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1) ) {
// 左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
if(mario.spdX > 0) {
mario.spdX -= 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
if(mario.spdX < 0){
mario.spdX += 0.3;
mario.x += mario.spdX;
count_flag += 1;
}
} else {
// 右キーの処理。移動・ダッシュ。
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX += 1.0;
}else {
mario.spdX += 0.3;
}
mario.x += mario.spdX;
}
// 左キーの処理。移動・ダッシュ。
if(CheckHitKey(KEY_INPUT_LEFT) == 1){
if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
mario.spdX -= 1.0;
}else {
mario.spdX -= 0.3;
}
mario.x += mario.spdX;
}
}
if(Buf[KEY_INPUT_C] > 0) {
if(!jumpflag) {
mario.spdY = 16;
jumpflag = true;
}else{
oti = 0.7;
}
}else{
oti = 1.2;
}
printf("%d",jumpflag);
mario.y -= mario.spdY;
mario.spdY -= oti;
if(mario.x < 0) mario.x = 0;
//if(mario.x > 640 - 32) mario.x = 640 - 32;
if((CheckHitKey(KEY_INPUT_Z))) {
if(mario.spdX > 8.0) mario.spdX = 8.0;
if(mario.spdX < -8.0) mario.spdX = -8.0;
}else {
if(mario.spdX > 5.0) mario.spdX = 5.0;
if(mario.spdX < -5.0) mario.spdX = -5.0;
}
if(count_flag > 1) {count_flag = 0; mario.spdX = 0;}
if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount = 0; jumpflag = false;}
if(mario.spdY > 30.0 ) mario.spdY = 30.0;
/*xxx:
mario.y += mario.spdY;
mario.spdY += oti;
if( mario.JumpCount == 0) {
if( Buf[KEY_INPUT_C] > 0) {
mario.JumpCount++;
}
}else{
if( Buf[KEY_INPUT_C] > mario.JumpCount) {
if(mario.JumpCount < 10) {
mario.spdY = 10;
}else if(mario.JumpCount == 10) {
mario.spdY = 15;
}
}
mario.JumpCount++;
}
xxx:*/
DrawFormatString(300,0,GetColor(0,0,0),"X : %f" ,mario.x);
DrawFormatString(300,20,GetColor(0,0,0),"Y : %f" ,mario.y);
DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);
//-------------------------------------------------------------------------
ScreenFlip();
wait_fanc();
}
DxLib_End();
return(0);
}
void wait_fanc(){
int term;
static int t=0;
term = GetNowCount()-t;
if(16-term>0)
Sleep(16-term);
t=GetNowCount();
return;
}
void fps(){
int i;
static int t=0,ave=0,f[60];
f[count%60]=GetNowCount()-t;
t=GetNowCount();
if(count%60==59){
ave=0;
for(i=0;i<60;i++)
ave+=f[i];
ave/=60;
}
if(ave!=0){
DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
DrawFormatString(0,20,GetColor(0,0,0),"%dms" ,ave);
}
return;
}
void GetKeyInput( int *KeyBuf ){
char damy[256];
GetHitKeyStateAll( damy ) ;
for( int i=0 ; i<256 ; i++ ){
if( damy[i] == 1 )
KeyBuf[i]++;
else
KeyBuf[i] = 0;
}
}
一応出来ました!!
悪かった点が確かなのかわからないので変えたところを書きたいと思います。
まず、if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount = 0; jumpflag = false;}
を書いたあとにジャンプの処理をしていたので、その前にジャンプの処理を書きました。
これにより、カクカクする動作が消えました。
次に地面についた時にjumpflagをfalseにしていなかったので追加しました。
コード:
if(Buf[KEY_INPUT_C] > 0) {
if(!jumpflag) {
mario.spdY = 16;
jumpflag = true;
}else{
oti = 0.7;
}
}else{
oti = 1.2;
}
これですが、直した点は、まずKEY_INPUT_C == 1を上記のに変えました。これはなぜできなかったのかわかないです。
次にCkeyを押している時にjumpflagがtrueのときだけoti = 0.7を実行するようにしました。最初はprintfデバッグで確認したらここにプログラムの流れがこなかったので色々試したら簡単にまとまってしまいました。
次はCkeyが押されていない時にjumpflagがfalseの場合のみ oti = 1.2を実行していたので、それを取り除きました。これにより地面より上にいる場合はキーに触れていなくても必ず下に落ちてくるようになりました。
おそらく以上のことを変えました。
久しぶりに昔のマリオをやってみたのですが、なかなかジャンプの綺麗さが違って驚きましたww
意外とジャンプが低く、大きいジャンプと低いジャンプの差がキャラ1つ分位ありました。
色々数値をいじってみたのですがなかなか本物に近づけません。
これ以外にも何らかの処理があるのでしょうか?
謎ですww
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 23:15
by softya(ソフト屋)
KEY_INPUT_C == 1がうまくいかない理由はKEY_INPUT_CとBuf[KEY_INPUT_C]をprintfして比べてみると分かると思います。
問題のジャンプですが、調べてみると面白い方法で計算しているみたいです。
「マリオのジャンプ実装法とVerlet積分 - Gemmaの日記」
http://d.hatena.ne.jp/Gemma/20080517/1211010942
出てくる言葉はややこしく見えますが、やっていることは簡単ですね。
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 23:30
by ボラ天神
出てくる言葉が難しくてわからない今日この頃ですねwww
一体どういうふうになっているのですかね
Re: マリオ風のジャンプについて
Posted: 2012年8月21日(火) 23:40
by softya(ソフト屋)
ボラ天神 さんが書きました:出てくる言葉が難しくてわからない今日この頃ですねwww
一体どういうふうになっているのですかね
「マリオのジャンプ実装法とVerlet積分(実践編) - Gemmaの日記」
http://d.hatena.ne.jp/Gemma/20080801/1217559803
まぁ、やって見たほうが早いと思います。
Re: マリオ風のジャンプについて
Posted: 2012年8月22日(水) 00:39
by ISLe
ボラ天神 さんが書きました:久しぶりに昔のマリオをやってみたのですが、なかなかジャンプの綺麗さが違って驚きましたww
意外とジャンプが低く、大きいジャンプと低いジャンプの差がキャラ1つ分位ありました。
色々数値をいじってみたのですがなかなか本物に近づけません。
これ以外にも何らかの処理があるのでしょうか?
謎ですww
スーパーマリオブラザーズのジャンプは大小の2種類ではないですよね。
#まさか最近のスーパーマリオは違うとか?
小マリオと大マリオで背の高さが違うので、足元を基準にします。
- 一瞬ボタンを押してすぐに離しても最低1ブロック(小マリオの高さ)分はジャンプする。
- ボタン押しっぱなしで垂直に飛ぶと4ブロック分ジャンプする。
- 移動しながらだとジャンプの高さは上がる。Bダッシュ最高速で5ブロック分に到達
実際の映像では押しっぱなしで上半分は等速に見えますね。
Re: マリオ風のジャンプについて
Posted: 2012年8月27日(月) 22:09
by ボラ天神
皆さん返信遅れてすみませんでした。
softya(ソフト屋) さん
URLありがとうございます!!
早速試してみたいと思います!!
ISLe さん
めっちゃ参考になりますww
実際のプログラムはどうなのでしょうかねww
頑張って試してみたいと思います。
ジャンプは一応これで解決としますが、今後もマリオ関係の質問をするかもしれませんのでよろしくお願いします。