またパズルゲーム
またパズルゲームを作りました。今度はなかなか良作となっています。
と、その話をする前に…、
このブログでいちばん検索されているワードは、なぜか「杏仁豆腐」なんですよね。
↓
杏仁豆腐の美味しい食べ方
http://dgen.hatenablog.com/entry/2015/04/29/184730
かなりいい加減に書きなぐって、プリンと一緒のごちゃっとしたあまり美しくない画像もアップしていますが、なぜだかよく検索されています。一応プログラミングがメインでやっているブログなので、それに関した検索流入も少しはありますが、「杏仁豆腐」が断然強いです。もっと杏仁豆腐をフィーチャーしたほうがいいんでしょうか?でもなあ…。これといって記事にするようなこともないですよ。杏の種子から作るところでも書いたらいいのかな。なんなら杏の種を植えて収穫するまでやりすますかっ!
いや、しませんっ!
だいたい杏が芽を出して実を結ぶまで何年かかるかも知りませんし、その長い間追跡ドキュメントするなんてこのブログの存在すらすっかり忘れていた私にできると思ってんのかーっ!
すみません。つい言葉を荒げてしまいました。よくわかりませんが勢いで書いただけです。本人も何に対して怒っているのかわかっていません。何はともあれ杏仁豆腐って美味しいよねってことが言いたかっただけです。
さて、前置きが長くなってしまいましたが、気分を入れ替え本題に入りましょう。杏仁豆腐のことはもう忘れてくださいね。あっ、でも今回は少し長くなりそうだからまた次回にしよっかな。いやいや、とりあえず途中まででも書いていくぞっ!
前回、前々回とあまりパっとしないものを紹介してしまいましたが、次はパズルゲームが好きならちょっとは時間が潰せるプロダクトとなりました。というのも前2作がてきとーな感じで終わってしまった反省と「もっと良いものを作りたい!」という創作意欲が出てきたので、多少なりともクオリティの高いものを作っていこうじゃないかと考えたからです。
今回の元となるゲームは「10×10」というパズルゲームです。最初にアップしたのはどこだか知りませんが、Yahoo や nifty などで遊べます。そのゲームをプレイした感触は評価したいんですが、単なるカジュアルゲームになってしまっているのが個人的に許せなかったので自分で作り始めました。
ルールは簡単で10×10のマスにブロックを置いていって縦横のラインを揃えるとそのラインが消えるというものです。ブロックが置けなくなったらゲームオーバー。これを私がアレンジしてどうなったかというと…。
まずブロックを回転できるようにしました。元のゲームでは向きが固定されているので「回転すれば置けるのに…」と、イラっとする場面が多かったからです。でも回転させると簡単になってしまうので、その分ブロックの種類を増やし難易度を上げました。またブロックの高さを5段階のランダムにしてラインが揃ったらそのラインを1段下げていくシステムにしました。それによって最大5回のコンボが発生しこれを狙ってプレイも熱くなります。もちろんコンボをつなげればそれだけ高得点となります。またラインが凸凹になるので難易度もアップします。
元ゲームでは得点があまりにもお粗末で、置いたブロックの数と消したラインによる得点が常に一定だったのでカジュアルゲームっぽさが加速していたわけです。ですから得点に関してはもっと付け加えて一度に一定以上のラインを消すと基礎点が上がるようにしています。こうすることでハイスコアを狙うにはちびちび消すのではなく大量消しが有効になってきます。でもこれが同時にトラップにもなっていて、大量消しを狙うと盤面が不規則に凸凹しやすくなって後からフォローするのが難しくもなったりならなかったり。
プレイが後半に差し掛かると1×1や2×1の小さい隙間ばかりでブロックが置けない状況になってきます。そこで登場するのがお助けアイテム!1ラインを1段下げたりブロックが無いマスを塗り潰すように埋めたり、使い方によっては差し迫った状況から逆転できます。使うタイミングや場所も結構考えてしまいますね。そしてそのアイテムはイージーモードでは最初から全種類持っていますが、他のモードでは自分で獲得していくしかありません。ここでもラインの大量消しのトラップにハマるように、複数ラインの同時消し(モードやレベルによる)でアイテムゲットとしました。
意外と実装してみてから面白いなと感じたのは自爆ボタンです。手詰まりになったときに自爆ボタンで置くべきブロックを全部破棄します。3回このボタンを使って次に押すとゲームオーバーになりますが、なにも手詰まりになってから押す必要もありません。今あるブロックが置けるとしてもあえて破棄することで次のブロックがイイ感じに置けるような状況も多々あるので、ある意味アイテムのひとつとして使う感覚にもなるんですよね。当初はブロックが置けない判定をするのがプログラム的に面倒なので作った自爆ボタンですが、新たな駆け引きの道具としてパズルを奥深くしています。
あとはおまけでブロックの見た目を選択できるようにしてあります。これは単に自分で納得のいくデザインのブロックが描けなかったのでいくつか描いている内に「せっかく描いたから全部使おう」となっただけですが…。
今回は細かい操作や見た目にも拘って作ったこともあり、今までの作品の中では最高傑作といっても過言ではありません。とはいってもやっぱり全体的に素人っぽさは隠せませんが…。まあ、これまで中途半端な作品ばかりでしたからね。たまにはちょっと気合を入れて作らないと!
あっ、BGM作らなかった…。
効果音はいくつか作ったけど。
パズル?
そういえば、このブログで紹介している作品は、以前は他にサイトを作ってそこからダウンロードできるようにしてありましたが、放置したままだったのでサーバーの契約期間が切れて現在はダウンロードできません。どちらにしたところでわざわざダウンロードしてプレイするほどのものは作ってません!(なぜか強気)実際にダウンロードした人がいるのかも把握しないままサイトは消滅してしまいました。
今は相変わらずC++をメインになんとな~くゲーム制作は続けていますが、最近「やっぱweb上でプレイできるのは大きい!」と今更ながらの視点で JavaScript を、こちらもなんとな~くですが覚えていこうかな、といった感じです。また新しくサイトを立ち上げて、自分で覚えながらその内容と様子をアップしていけたらな~と思う次第で御座います。
で、話は前回に戻って最近のプロダクトを紹介。これも特に何が面白いというわけではないんですが…。簡単なパズルゲームを作りました。ただ絵柄を並び替えて絵を完成させるだけのこれといって特徴のないゲームです。
なぜこれを作ったかというと、モバゲーで同じパズルがあるんですが、一度クリアしてしまうともう遊べないんですよね。全部解いてしまうと次のアップデートまで1年とか放置されるので、なんだか欲求不満になるんです。「誰も課金しないようなコンテンツがよくここまで長続きするよな」なんて考えながらも「もっと・・・パズル・・・欲しい・・・」となっている自分に気づいたわけです。そんなこんなでサクっと作っちゃいました。
画像を5×5のパネルに切り分けてシャッフル、それを並び替えるだけです。パズルと称するには計算などを必要としない気楽な感じがハマるんですかね。好きな画像を取り込んでプレイできるので、ネットで拾った画像や自分で撮影した写真などを使って無限プレイが可能です。強い拘りというわけでもないですが、プレイする画像を自動でパズルの盤面に合わせると縦と横の比率がおかしくなることもあるので、そこはサイズを編集した画像を準備するところは譲れなかったところですかね。私しかプレイしないからそこまで便利にする必要もないし。だからできるだけ手を抜いて作ってあります。
実際に画像を取り込んでプレイしてみると、パズルとしての難易度は結構高かったりもします。というのも、パズルにすることを前提としてなんて考えずに画像を取り込むので、背景が空のようなほぼ一色のパネルがいくつも出来上がりなかなか見分けるのが困難です。自作ゲームのキャプチャなども取り込んでプレイしてみましたが、空のようにグラデーションさえ無いまったく同じパネルが5枚くらい出てきて、あとは勘に頼って入れ替えるしかありません。さすがに自分でやったことに文句を言っても意味はないし、それはそれで取り込んだ人の味も出るもんだということにして納得しています。(モバゲーのパズルでも同様の難解なやつはあったし…)
今回のパズルはこれといって難しいことはしていません。ほんとにサクっと作った感じですね。で、作り終わった感想が「もうこれやらないな…」。そうなんです。いざ作って「無限にできる!」となると欲求が満たされるというか魅力が半減してしまうんですよね。人間って面白い!
よくわからないもの
またしても1年以上放置のままでした(汗。タイトルに”日常”とありますが、1年に1度の更新で日常というのもなんだかな~と思う今日この頃です。
あれから密かにいくつか作ってはいます。ですがこのブログのことをすっかり忘れていて数日前に「あっ、そうだ!」てな具合で思い出したので、その作ったいくつかをざざっと紹介していきます。
最初に作ったのは、はっきりいって失敗作です。
クッキークリッカーというゲームはみなさんご存知でしょうか。つい最近もバージョン2が更に更新されました。今ある放置ゲーの元となったゲームで、ゲーム内容の単純さゆえにかなりの人がハマったようです。このゲームの内容を変えて作ったのですが、いろいろと残念な結果となりました。
具体的なモチーフが浮かばないまま作り始めたので、最初はクッキークリッカーでいう農場や工場といった施設を何も具体的なものを準備せずただ数字だけ並べていたので何が目的なのかまったくわからないことになっています。加えて、クッキーとは別の動く何かをクリックしていったほうが面白いだろうと思って施設を購入した分だけその動く何かを登場させました。こちらもイメージが浮かばず結局以前作った phase of evolution のブロックをとりあえず使いまわしてしまいました。ちょうど施設の数とブロックの数が20で同じだったし、ブロックには通し番号が描いてあったので「わかりやすい!」とかなんとか。
そのまま作り続けて、最終的にRPGっぽい風体に仕上げようと考えたのがほぼ出来上がった頃で、施設は装備や魔法など強くなるイメージのもの。動く何かはモンスターに置き換えたかったのですが、描くのが面倒だったので放置して作り続けるという怠慢。これぞ放置ゲー!違う?
そういえばいちばん大事な大きなクッキーに相当するものも描いてなかった。画面右側が施設で左下が動く何かのスペースだったので左上の本来なら大きなクッキーを表示する何もないところをひたすらクリックするというシュールな感じに仕上がってます。
そして残念具合の最たるところは、これはちょっと技術的な話になってきますが、でかい数字が扱えないということ。32bit の double型だと有効数字が15桁くらいなんですよね。かなり大きな数字でも計算できなくはないですが、15桁に入らなかった数字は丸められて無かったことになります。単純に施設が20個あって、その価格や効果量を10倍10倍にしていくと最低20桁は必要になります。20桁となると下から5桁は0が並ぶことになってしまうし、5桁以下の数値を加算しても意味がありません。もちろんそれを回避する方法はいくつかありますが、ほぼ完成した状態から15桁を超える可能性のある変数すべてを修正するのはそれほど膨大ではないコードですが面倒です。面倒なのですぐ諦めました(笑)。まあ、それでなくとも中途半端な仕上がりなのでそこに拘る必要もないかな、といった感じです。
このゲームの名前はゲーム内容が完成してから付けています。最後までイメージできなかったからですね。で、付けた名前が「エレメント 八つの秘宝」。エレメントって何だよ!とツッコミを入れたくなるようなゲーム内容です。八つの秘宝は転生したときのパワーアップ要素が八つあったのでてきとーに付け足してみました。わっはっは…。でもって取って付けたようにタイトル画面を作って完成。
よほど「欲しい!」という人でも現れない限りこのゲームが出回ることはないでしょう。
擬似3D
いやあ、前回の記事から実に1年以上が経過しました。あれからまともにコードを書いてません…汗。ってことで、ちょっと試したいことを久々にプログラミングで表現してみました。
みなさん「平行法」はご存知でしょうか?2つの画像を並べて、右の画像を右目で、左の画像を左目で見ると立体的に見えるという一種の錯視です。これを2Dの画像を使ってリアルタイムで画面上に描画してみたかったんです。あまり形状が複雑なものは計算も複雑になるので相当時間がかかると思います。ですので今回は単純な直方体を描画していきます。
もともと2D画面上でどうやって3Dを表現するか興味があったのですが、今回のようにカメラアングルなどを気にしない簡易的なものであればそれほど難しく考える必要はありません。
まずは遠近法でどのくらいの距離ならどのくらいの大きさで描画すれば良いか考えます。見た目の大きさは距離に反比例するので単純にz値(奥行き=距離)で割るだけです。同じ要領で少し付け加えると画面上の縦と横の位置も求められます。それを直方体の8つの頂点それぞれ算出し、DrawModiGraph関数(画像を自由に変形させる)で1面ずつ描画していきます。
int DrawModiGraph( int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4,
int GrHandle , int TransFlag );
このとき注意したいのはzソートです。簡単に説明すると、奥にあるものから描画しなければ最終的に画面に出来上がるのはへんてこな画像になるということです。それを考慮したつもりで、直方体の上下左右そして最後に正面を描画しましたが、「???」。左右の面が上下の面を侵食してうまく描画できませんでした。「これって見える角度によって描画順を変えないといけないなあ…」そうなんです。zソートってこんな単純な直方体1個の描画でも問題になるんです。
めんどーなことが嫌いな私はその問題を無視するかのように、見える角度を少しずらして上の面が見えないようにしましたとさ笑。そして左・右・下・正面の順で描画することで事実上問題を回避したと同じ効果を得ました(なんと手ぬるい且つ卑怯な!)。こういったところは私は職業プログラマーに向いてないのかもしれません…。
とはいえ、これで直方体を描画することができました。あとは10個くらい同時に動かしながら右目用と左目用に少し角度を変えて描画していきます。角度といっても三角関数などは使用しません。右目用の画面は手前にくるほど左へ移動し、左目用の画面は手前にくるほど右へ移動するようにずらすだけです。これでお仕舞い。
・・・ではなく、直方体相互のzソートくらいはやっておきましょう。1フレームごとにz値の大小を for文で1回比較するという世にもてきとーなソートですが、奥から手前に真っ直ぐ一定速度で移動するだけなので十分機能します。そのソートした結果を配列に突っ込んで、その配列順に描画していきます。
これで完成です。
↓こんな感じ
にしても、最近の(昔のもそうだけど…)3DCGを見てると「こんなのどうやって作ってるんだ!?(プログラム的に)」と思わざるをえません。単調な擬似3Dでさえ苦戦する私からしたら永遠に手が届きそうにありません。頭良い人っていいね!(なんて横目で羨望の眼差し)
ちなみにコードの掲載は無しです。試作として作ったこともあり、ざっくりと書いているので強引な修正など無駄な部分ばかりで見せるレベルではありません(いつものこと!?)。あしからず。
シルバーウィークと次回作
いつの間にやら世間にはシルバーウィークという言葉が浸透していますが、みなさん休んでますか~?あいにく私は5連休が4連休へと減ってしまいました。連休が終わってもしばらく多忙な毎日です。
まあここでちょっと愚痴を書いてみますが…(笑)職場の段取りが悪いんですよね。また関連会社の段取りも悪い。だから余計な仕事が増えたり、中断して無駄な時間を過ごしたりということが頻繁に発生します。おかげで自分の仕事に集中できずミスも増える始末。「お前ら!【段取り八分仕事二分】って言葉知らんのかっ!」と言いたくなります。いや、実際それっぽいことを言ったり態度で示してますけどね(苦)。それでも同じ間違いを何度も繰り返されるので、もう呆れてそろそろ転職を考えようかというところです。
はい。愚痴終了!
これを機にプロのプログラマーとして技術を覚えたいな~なんて気持ちはありますが、如何せん年齢的な制限に引っ掛かるのは火を見るよりも明らかなので、プログラミングはとりあえず趣味の範囲で続けていきます。
でも今の仕事を続けている内は疲労が激しいので、ここでの創作ペースはかなり落ちると思います。現に「真円プロジェクト」が完成してから、何を作るかも考えていない状態です。作りたいものは山ほどありますが、疲れていると落ち着いて創作しようという意欲が沸いてこないんですよね。困った、困った。
ということで、次回作についてはひとまず棚上げしてのんびりやっていく予定です。ブログの更新も以前に増して少なくなるかもしれません。
「真円プロジェクト」完成!
う~ん…。一応完成しましたが、やはりペンタブでの動作は確認出来ていません。これを機にペンタブを購入しようとも考えましたが、今は他に買いたいものがあるので、とりあえず購入リストに入れて後回しです。そんなこんなで、ペンタブでの動作を確認してくださる心優しい方を待っています。
↓「真円プロジェクト」はこちらからダウンロード出来ます。
http://tenkomorituuhan2.com/products/truecircle/top.html
ほとんど検索していないので確かではありませんが、おそらく真円具合を測定するソフトは他にありません。真円の練習には、是非とも「真円プロジェクト」をご使用ください。
さて、プログラミングの内容に移りますが、今回微妙に苦戦したのは不正処理です。
①途中から逆向きに円を描く
②画面からはみ出る
③一定時間経過
上記の行為を不正とみなし得点を0にしていますが、①の判定が思ったよりも複雑で、一周の判定とダブらないように不正をチェックさせるのに時間がかかりました。ここら辺も私の弱点ですね。最初からある程度設計してから取り掛かれば曲がりなりにも1つの関数にまとめたり出来るのでしょうが、思いつきで追加していくので、ぐだぐだと後から付け足して最終的に冗長したコードに変貌を遂げます。数をこなしていけば、自然と効率が良く読みやすいまとまったコードが書けるようになっていくのかな、なんて漠然と考えていますが、意識していかないとダメですね。
では、ソースコード公開です。今回のコードは短めですが、無理に理解しようとすると混乱します。私にだけ理解出来るコードです。なので、よほどチャレンジ精神旺盛でない限りコードの使用はお控えください。使用した結果、何が起きても一切責任は取れません。取りません。
/*################################################### True Circle Project 真円プロジェクト ###################################################*/ #include <math.h> #include "DxLib.h" #define WX 640 //ウインドウサイズ #define WY 640 #define POSMAX 1000 //座標記憶最大数 #define PI 3.141592653589793238 //円周率 int x[ POSMAX ]; //座標 int y[ POSMAX ]; double dis[ POSMAX ]; //中心からの距離 char totalflag; int highscore[ 5 ] = { 0 }; int score[ 3 ]; //ハンドル int GHnum[ 3 ]; //数字 int GHword[ 9 ]; //文字(大) int GHword2[ 6 ]; //文字(小) int GHtitle; //タイトル //プロトタイプ宣言 void Title(); void DrawTitle(); void Circle(); int Play(); void FadeIn(); void FadeOut(); void Save(); void Load(); //WinMain int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { SetOutApplicationLogValidFlag( FALSE ); //ログ出力しない SetMainWindowText( "True Circle Project" ); //ウインドウタイトル指定 SetGraphMode( WX , WY , 32 ); //ウインドウの大きさとカラービット数指定 ChangeWindowMode( TRUE ); //ウインドウで表示 SetDrawScreen( DX_SCREEN_BACK ); //ちらつき防止設定 SetWaitVSyncFlag( TRUE ); //フレーム同期 SetMouseDispFlag( TRUE ); //マウスカーソル表示 SetWindowUserCloseEnableFlag( FALSE ); //×ボタンで終了しない SetUseDirectInputFlag( FALSE ); //ペンタブ使用環境 if( DxLib_Init() == -1 ) return -1; //画像読込 LoadDivGraph( "img/num.png" , 3 , 3 , 1 , 60 , 64 , GHnum ); LoadDivGraph( "img/word.png" , 9 , 9 , 1 , 128 , 64 , GHword ); LoadDivGraph( "img/word2.png" , 6 , 6 , 1 , 160 , 48 , GHword2 ); GHtitle = LoadGraph( "img/title.png" ); //記録読込 Load(); //メインループ while( totalflag != -1 ){ switch( totalflag ){ case 0: case 2: Title(); break; case 1: Circle(); break; } } DxLib_End(); return 0; } void Title(){ //タイトル ############################## DrawTitle(); while( 1 ){ if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){ totalflag = 1; break; } if( ( GetMouseInput() & MOUSE_INPUT_RIGHT ) != 0 ){ totalflag = -1; break; } if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ){ totalflag = -1; break; } WaitVSync( 1 ); } FadeOut(); } void DrawTitle(){ //タイトル描画 ######################## SetFontSize( 16 ); DrawBox( 0 , 0 , WX , WY , 0xffffff , TRUE ); if( totalflag == 2 ){ DrawCircle( WY / 2 , WY / 2 , WY / 2 -20 , 0xaaaaaa , FALSE ); } else { FadeIn(); //ぐるっと円描画 double s1 = 0; double s2 = WY / 2; double c1 = 0; double c2 = WY - 20; for( double i = 0 ; i > -PI * 2 - 0.03 ; i -= 0.03 ){ s1 = ( WY / 2 + sin( i ) * ( WY / 2 - 20 ) ); c1 = ( WY / 2 + cos( i ) * ( WY / 2 - 20 ) ); DrawLine( ( int )s2 , ( int )c2 , ( int )s1 , ( int )c1 , 0xaaaaaa , 2 ); s2 = s1; c2 = c1; ScreenFlip(); } } DrawGraph( WY / 2 - 256 , 180 , GHtitle , TRUE ); DrawGraph( WY / 2 - 196 , WY / 2 + 20 , GHword[ 7 ] , TRUE ); for( int i = 0 ; i < 5 ; i++ ){ DrawFormatString( WY / 2 - 160 , WY / 2 + 90 + i * 30 , 0x777777 , "%d" , highscore[ i ] ); } DrawString( WY / 2 - 40 , WY / 2+60 ,"left click to START", 0x777777 ); DrawString( WY / 2 - 40 , WY / 2 + 90 ,"right click or esc key to EXIT", 0x777777 ); if( totalflag == 2 ){ FadeIn(); } ScreenFlip(); } void Circle(){ //プレイサークル ######################## for( int i = 0 ; i < 3 ; i++ ){ DrawBox( 0 , 0 , WX , WY , 0xffffff , TRUE ); //中心点 DrawCircle( WY / 2 , WY / 2 , 3 , 0x999999 , TRUE ); FadeIn(); int GHfade = MakeGraph( WX , WY ); GetDrawScreenGraph( 0 , 0 , WX , WY , GHfade ); //「n回目」描画 for( int j = 0 ; j < 256 ; j += 5 ){ DrawGraph( 0 , 0 , GHfade , TRUE ); SetDrawBlendMode( DX_BLENDMODE_ALPHA , j ); DrawGraph( WY / 2 - 90 , 50 , GHnum[ i ] , TRUE ); DrawGraph( WY / 2 - 30 , 50 , GHword[ 0 ] , TRUE ); SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ); ScreenFlip(); } WaitVSync( 30 ); for( int j = 255 ; j > -1 ; j -= 5 ){ DrawGraph( 0 , 0 , GHfade , TRUE ); SetDrawBlendMode( DX_BLENDMODE_ALPHA , j ); DrawGraph( WY / 2 - 90 , 50 , GHnum[ i ] , TRUE ); DrawGraph( WY / 2 - 30 , 50 , GHword[ 0 ] , TRUE ); SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ); ScreenFlip(); } //「始め」描画 DrawGraph( 0 , 0 , GHfade , TRUE ); DrawGraph( WY / 2 - 64 , 50 , GHword[ 1 ] , TRUE ); ScreenFlip(); WaitVSync( 40 ); DrawGraph( 0 , 0 , GHfade , TRUE ); ScreenFlip(); DeleteGraph( GHfade ); score[ i ] = Play(); FadeOut(); } //総合結果 SetFontSize( 32 ); DrawGraph( WY / 2 -128 , 50 , GHword[ 5 ] , TRUE ); DrawGraph( WY / 2 , 50 , GHword[ 3 ] , TRUE ); for( int i = 0 ; i < 3 ; i++ ){ DrawGraph( WY / 2 - 188 , i * 100 + 150 , GHnum[ i ] , TRUE ); DrawGraph( WY / 2 - 128 , i * 100 + 150 , GHword[ 0 ] , TRUE ); DrawFormatString( WY / 2 + 20 , i * 100 + 170 , 0x777777 , "%d" , score[ i ] ); } int ttl = score[ 0 ] + score[ 1 ] + score[ 2 ]; DrawGraph( WY / 2 - 128 , 450 , GHword[ 6 ] , TRUE ); DrawFormatString( WY / 2 + 20 , 470 , 0x777777 , "%d" , ttl ); //スコア更新 if( highscore[ 4 ] < ttl ){ highscore[ 4 ] = ttl; for( int i = 3 ; i > -1 ; i-- ){ if( highscore[ i ] < ttl ){ highscore[ i+1 ] = highscore[ i ]; highscore[ i ] = ttl; } } DrawGraph( WY / 2 - 128 , 550 , GHword[ 7 ] , TRUE ); DrawGraph( WY / 2 , 550 , GHword[ 8 ] , TRUE ); Save(); } ScreenFlip(); while( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){ WaitVSync( 1 ); } while( ( GetMouseInput() & MOUSE_INPUT_LEFT ) == 0 ){ WaitVSync( 1 ); } FadeOut(); totalflag = 2; } int Play(){ //真円描画 ########################### double radatan; //中心からの角度 int quart; //円を4分割 int qstart = 0; //4分割の始点 double start; //始点の角度 int frame = 0; //フレーム数 int round = 0; //一周フラグ while( 1 ){ //クリック待ち WaitVSync( 1 ); if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){ GetMousePoint( &x[ 0 ] , &y[ 0 ] ); if( ( -1 < x[ 0 ] ) && ( x[ 0 ] < WY ) && ( -1 < y[ 0 ] ) && ( y[ 0 ] < WY ) ) break; } } int flag[ 4 ] = { 0 }; //4分割の通過フラグ int v = 0; //右回り左回り int qtemp = -1; //4分割の現在位置記憶 while( frame < POSMAX ){ //マウス座標取得 GetMousePoint( &x[ frame ] , &y[ frame ] ); //画面からはみ出し if( ( x[ frame ] < 0 )||( WX < x[ frame ] )||( y[ frame ] < 0 )||( WY < y[ frame ] ) ) break; //中心からの角度取得 radatan = atan2( ( double )( x[ frame ] - WY / 2 ) , ( double )( y[ frame ] - WY / 2 ) ); //4分割の現在位置 quart = ( int )( ( radatan + PI ) / ( PI / 2 ) ); if( quart < 0 ) quart = 0; if( quart > 3 ) quart = 3; //次の4分割に侵入 if( quart != qtemp ){ flag[ quart ]++; if( ( v == 0 ) && ( qtemp != -1 ) ){ //向きが決まっていなければ決める v = -1; if( qstart < quart ) v = 1; if( ( qstart == 3 ) && ( quart == 0 ) ) v = 1; if( ( qstart == 0 ) && ( quart == 3 ) ) v = -1; } //戻り不正 if( flag[ 0 ] + flag[ 1 ] + flag[ 2 ] + flag[ 3 ] > 6 ) break; if( ( flag[ quart ] > 1 ) && ( flag[ 0 ] * flag[ 1 ] * flag[ 2 ] * flag[ 3 ] == 0 ) ) break; qtemp = quart; } if( frame > 0 ){ //線描画 DrawLine( x[ frame - 1 ] , y[ frame - 1 ] , x[ frame ] , y[ frame ] , 0x666666 ); } else { //始点 start = radatan; qstart = quart; } //中心からの距離取得 int xf = x[ frame ] - WY / 2; int yf = y[ frame ] - WY / 2; dis[ frame ] = sqrt( (double)( xf * xf + yf * yf ) ); //一周判定 if( flag[ qstart ] == 2 ){ int fx = flag[ 0 ] * flag[ 1 ] * flag[ 2 ] * flag[ 3 ]; if( v == 1 ){ if( ( start < radatan ) && ( fx > 1 ) ) round = 1; if( ( flag[ ( qstart + 1 ) % 4 ] == 2 ) && ( fx > 1 ) ) round = 1; } else { if( ( start > radatan ) && ( fx > 1 ) ) round = 1; int temp = qstart - 1; if( temp < 0 ) temp = 3; if( ( flag[ temp ] == 2 ) && ( fx > 1 ) ) round = 1; } } ScreenFlip(); frame++; if( round == 1 ) break; } //結果 if( flag[ 0 ] * flag[ 1 ] * flag[ 2 ] * flag[ 3 ] * round > 0 ){ double min = 9999; double max = 0; double ave = 0; double bure = 0; int speed = ( POSMAX * 2 - frame ) / 20; int sc = 0; for( int i = 0 ; i < frame ; i++ ){ if( min > dis[ i ] ) min = dis[ i ]; if( max < dis[ i ] ) max = dis[ i ]; ave += dis[ i ]; } ave = ave / frame; bure = ( 1 - min / max ) * 100; sc = ( int )( ave / 6 * speed * ( 100 - bure ) * ( 100 - bure ) / 100 ); DrawCircle( WY / 2 , WY / 2 , ( int )min , 0xffaaaa , FALSE ); DrawCircle( WY / 2 , WY / 2 , ( int )max , 0xffaaaa , FALSE ); DrawCircle( WY / 2 , WY / 2 , ( int )ave , 0xaaffff , FALSE ); DrawGraph( WY / 2 - 64 , 30 , GHword[ 3 ] , TRUE ); for( int i = 0 ; i < 6 ; i++ ){ DrawGraph( WY / 2 - 180 , i * 50 + 100 , GHword2[ i ] , TRUE ); } DrawFormatString( WY / 2 + 10 , 120 , 0x777777 , "%f" , max ); DrawFormatString( WY / 2 + 10 , 170 , 0x777777 , "%f" , min ); DrawFormatString( WY / 2 + 10 , 220 , 0x777777 , "%f" , ave ); DrawFormatString( WY / 2 + 10 , 270 , 0x777777 , "%f" , bure ); DrawFormatString( WY / 2 + 10 , 320 , 0x777777 , "%d" , speed ); DrawFormatString( WY / 2 + 10 , 370 , 0x777777 , "%d" , sc ); ScreenFlip(); while( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){ WaitVSync( 1 ); } while( ( GetMouseInput() & MOUSE_INPUT_LEFT ) == 0 ){ WaitVSync( 1 ); } return sc; } else { if( frame == POSMAX ){ //時間切れ DrawGraph( WY / 2 - 64 , 30 , GHword[ 4 ] , TRUE ); } else { //不正(はみ出し・戻り) DrawGraph( WY / 2 - 64 , 30 , GHword[ 2 ] , TRUE ); } ScreenFlip(); while( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){ WaitVSync( 1 ); } while( ( GetMouseInput() & MOUSE_INPUT_LEFT ) == 0 ){ WaitVSync( 1 ); } return 0; } } void FadeIn(){ //フェードイン ########################## int GHfade = MakeGraph( WX , WY ); GetDrawScreenGraph( 0 , 0 , WX , WY , GHfade ); for( int i = 0 ; i < 256 ; i += 5 ){ DrawBox( 0 , 0 , WX , WY , 0xffffff , TRUE ); SetDrawBlendMode( DX_BLENDMODE_ALPHA , i ); DrawGraph( 0 , 0 , GHfade , TRUE ); SetDrawBlendMode( DX_BLENDMODE_NOBLEND , i ); ScreenFlip(); } DeleteGraph( GHfade ); } void FadeOut(){ //フェードアウト ###################### int GHfade = MakeGraph( WX , WY ); GetDrawScreenGraph( 0 , 0 , WX , WY , GHfade ); for( int i = 255 ; i > -1 ; i -= 5 ){ DrawBox( 0 , 0 , WX , WY , 0xffffff , TRUE ); SetDrawBlendMode( DX_BLENDMODE_ALPHA , i ); DrawGraph( 0 , 0 , GHfade , TRUE ); SetDrawBlendMode( DX_BLENDMODE_NOBLEND , i ); ScreenFlip(); } DeleteGraph( GHfade ); } void Save(){ //書込み ################################ FILE *fp; errno_t error; if( ( error = fopen_s( &fp , "save.sv" , "wb" ) ) != 0 ){ //エラー }else{ fwrite( highscore , sizeof( int ) , 5 , fp ); fclose( fp ); } } void Load(){ //読込み ################################ FILE *fp; errno_t error; if( ( error = fopen_s( &fp , "save.sv" , "rb" ) ) != 0 ){ //エラー }else{ fread( highscore , sizeof( int ) , 5 , fp ); fclose( fp ); } } |
冷やし中華とペンタブ
なにかと忙しく疲れてしまい、休日になると半日を昼寝で過ごしてしまうなんてことも…。プログラミングのために時間を割くこともままならなず、ブログからも足が遠のくばかりです。一番暑い時期は過ぎ去りましたが、厳しい残暑は続きそうで、暑さによる倦怠感も敵ですね。
と、後ろめたいことはこの辺にして、少し元気が出そうなメニューを紹介します。・・・メニューというほどのものではありませんが、この暑い夏にぴったりの涼しげなアレです。さっぱりした醤油ダレでつるつるっといただきます。「〇〇〇始めました」なんて張り紙を見かけると「もう夏か…」と、それっぽく感慨深げに言ってみたりするお年頃の私です(笑
そう!それは冷やし中華です。この冷やし中華が格段に美味しくなるアレンジを見つけてしまったのでシェアします。
超簡単!たったひと手間で夏のダルさ解消!冷やし中華のアレンジレシピ
すみません。ちょっと大袈裟にタイトルを付けてみたかったんです…(汗)。でも超簡単は本当です。では作り方を。
①ふつーに冷やし中華を作る。
②オレンジを角切りにして添える。
以上
そうなんです。オレンジを加えるだけです。冷やし中華の醤油ダレは柑橘系の果汁を使っていることが多く、オレンジとは相性抜群です(胡麻ダレは別です)。醤油ダレが甘いので、オレンジはどちらかというと酸味より甘味が強いバレンシアオレンジなどが向いている気がしますが、そこはお好みで。オレンジの皮を包丁で剥いて(白いところは渋みが出るのできれいに剥く)角切りにするだけなので、簡単おすすめです。ぜひお試しを!
お近くのスーパーにオレンジが無かったら
↓
楽天で「バレンシアオレンジ」を検索
日本のみかんだと味がボヤケそうです。オレンジの掛け合わせ品種である「せとか」などは冷やし中華に合いそうですが、酸味が足りない感じですかね~。といっても収穫時期は冬から春にかけてなので、この暑い時期では冷凍したものくらいしか出回っていませんが…。柚子やカボスなどの皮や絞り汁を使うことはありますが、果肉をごろごろとぶち込むには、やはりオレンジが良さそうです。
夏は販売終了していますが、みかんの大トロなんて呼ばれています
↓
楽天で「せとか」を検索
・・・え~っと、話は変わって「真円プロジェクト」はというと…。ほぼ完成しました。ただ、私がペンタブを所持していないばかりに、ペンタブによる動作確認が取れていません。ペンタブのプログラムを組む人が少ないせいか、検索しても「これだ!」という情報がありません。一応ペンタブを使用するための最低限の処理は追加しましたが、それでしっかり動くかは謎のままです。なのでこのままリリースするかどうかちょっと迷っています。とりあえずマウスでは動作しています。