「インスタンス」を含む日記 RSS

はてなキーワード: インスタンスとは

2019-07-08

anond:20190708174643

いやいやいやいや、関数内の変数を参照しているかインスタンス内の変数を参照しているかを瞬時に見分けられるようにするオプションなんかデフォルトじゃその2種には搭載されてない訳だが?

2019-07-03

anond:20190703132229

取り敢えずmstdn.jpを使っておけば良いと思う

MastodonにはTwitter過去持ってた機能のUserStreamsに該当するlocal Timelineがあるから、mstdn.jpで「音楽趣味なんだけどそれにあったMastodonインスタンスある?」とか「ガジェット好きなんだけど良いMastodonサーバーある?」とかある程度の情報を載せて質問すると、mstdn.jpユーザーの誰かが丁寧に教えてくれると思うぞ

mstdn.jp性質として2ちゃんねるでいうところのラウンジ板とか初心者質問板のような役割を持っている

自身Mastodonインスタンス運営したい場合もmstdn.jp質問をすると既にインスタンス運営している管理者を紹介してくれたり、インスタンス管理者自身リプライしてくるはずだから質問すると良い

ちなみに上手く運営すると年間5,000円も掛からないのでインスタンス管理者の中には大学生高校生すら居る

anond:20190703040517

Mastodonってまだあるのか。

中央集権じゃないとなんかどこ行っていいか分かんないからずっと敬遠してる間に話聞かなくなったイメージだった。

インスタンス(?)運営するにはサーバ代かかるイメージもある

anond:20190703130249

多少独裁的に運営しても、インスタンス内で一定の支持を得られるなら、個人の持ち物だし、文句の言いようがないからねぇ。

2019-06-14

Oracleが嫌い

ぶっちゃけタルいのがすげー嫌。


Oracle DBの使い方を習得するのに、一番最初に用意すべきなのはパソコンでもサーバでもない。

一にも二にも教科書である

その教科書で、まずはスキーマインスタンスアーカイブログREDOログといった、Oracle DBの仕組みや概念学習する。

次にそれが実際のサーバ上でどんな風に見えていて、どうオペレーションするか…というアプローチを取らないと、絶対に動かないようにできている

それがOracle DBなのだ

あーもうすげーめんどくせー。

なんでこんなにもったいぶっていて、無駄に固いんだか。覚えにくいことこの上ない。

正直、いい加減にしろアホ!と何度思ったかからない。


それに比べると、PostgreSQLフリーソフトなのに本当によくできている。

無駄な前置きは一切なしで、実際にいじりながら覚えていけるのでハードルが超低い。

てか、こういうのでいいんだよこういうので。


そもそもOracleのような「教科書と授業」みたいな形式で覚えてくのって、ストレージアプライアンスを扱うのも仕事のうちという構築や運用人間ならともかく、プログラマにとっては全く水が合わない。

だってCOBOLFortranが主流だった大昔ならいざしらず、開発の世界じゃそういうのはC言語が出た時点で時代遅れになってるから

まじで勘弁してほしい。

2019-06-12

今こそw3mを使おう

w3mが(個人的に)アツい。

https://ja.wikipedia.org/wiki/W3m

テキストベースWebブラウザです。

昨今のサイトを見るにはとても不便で、操作性も何もかも非効率だけども、ブラウジングがとても新鮮なものになるよ

いかポエム

CDが売れなくなっている昨今、EPLPとかレコード好調らしい。

なんかそんな記事を見た中に、

「もはや音楽聴くことに娯楽的意味がなくなってしまい、CDセールスが衰退、アーティスト音楽のみで身を立てることが困難になっている中で、

音楽聴く”ことを愛でるようになった人がいる。

ライブに行き生演奏を目で体で聴くことで原初的感動を受ける人や、繊細なアナログメディア音楽享受する”儀式行為”により、新しい価値見出している人がいるため」

というようなことが書いてあって、なるほどなあと思った。

効率無視した献身的行為、ある種の狂信とも言うべき自慰的な活動こそが、拡散してしまいがちなアイデンティティを収斂するための一助になっていると考えているので、

それが音楽であれ、ピュアオーディオであれ、ルリ儀式筋トレ政権批判ガチャ課金、なんにでも没頭できるものが見つかるということはとても喜ばしいと思う。(誰かに迷惑をかけなければ)

音楽ほど歴史が長くないが、Webブラウザも年々大きく変動している最中で、研究者ツールだったもの大衆向けに整備され、一般化されるコンテンツに合わせてWWWの利用も複雑化している。

SNSと高度に連携したスマホファースト無味乾燥に大量消費されるコンテンツを見ていると、WWWを見るという行為を愛で、儀式行為価値見出しても良いように思う。

きっかけとしては何年か前のYAPCで、

インターネットを介したコミュニケーションでは情報が多すぎる、たくさん情報を受け渡しすると疲弊する。

情報量を極限まで削ることで、原初的な伝わったことが嬉しいという気持ちを得られる。

→だからモールス信号を使う」

といったネタのようなLTを見たこと。

ここからw3m適当Webブラウジングをするのが習慣になった。

原理主義というならLineModeBrowserとかLynxとかを選ぶべきなのだろうが、

日本発というアニミズム的発想(とドキュメントの多さ)からW3mを選んだ。

何よりも、w3mは「WWW-wo-Miru」の略だというと、上にあげた「WWWを見る」という行為儀式意味を持たせるためには必要な要素だと思われた。

最近だとBrow.shという画像も何とかテキストで表示してやろうという意欲的なものもあるんだけども、これは端末の解像度依存が大きいため断念。

というか画像必要であれば普通ブラウザ環境も使うという腥っぷり。

twitterは、twtermを使ってこれも余計なTLチェックが不要となった。

というような落書きを、適当EC2インスタンス上のw3mから書いている。

EC2tmux + w3m + twterm という環境をほぼ放置してあり、コマンド一発でほぼ同じ環境無料AWSを乗り継いで利用できるようにしてある。

はてブテキストベースで閲覧する方法を探している。それがあれば、より原初的感動を持ってクソのようなコメントを投げ合えるパラダイスが待っていることは自明である

2019-04-21

インターネットゾーニングの話

くそ長い話なので注意

最近TwitterロリキャラのR18イラストを描くアカウントへの規制が厳しくなってきたらしい。

そういったアカウントの凍結は前からあったが、最近特に見つかり次第凍結されている印象だ。

ぶっちゃけしまうと私はそういうイラストが好きなので、個人的には少し残念な状況ではある。

ただ、だからといって「表現の自由を守れ!」なんてTwitter社にケチをつけたいとは全く思わない。

みんな知ってる通り、日本という国はロリエロ絵に対する規制がかなり緩いが、世界的に見れば法律NGとしている国も少なくないし、国際的な流れは完全に規制寄りだ。

そんな状況では、いくら日本ユーザーが多いTwitter社でもロリエロ絵を看過できなくなって当然だと思う。

さて、それではそもそもロリエロ絵がTwitterなどのSNS上で投稿拡散されることの問題とはなんだろう。

ロリコンが増えることも社会的にはマイナスではあるが、これについては言論思想の自由で見逃されていい範囲だと思う。社会的プラス思想のみ肯定する世界になったら、それは単なるディストピアだ。

なので、間違いなく一番問題なのは「見たくない人の目に触れてしまう」ことだと思う。

すこし前に話題になった「お父さん、あれ気持ち悪い」発言だって、見たくないのに目に入ってしまうのが原因だし、他の既出問題もたいていここが原因だろう。

これの対策一見すると簡単で、「見たくない人が見ないところで投稿拡散すればいい」という「自主ゾーニングなのだけど、私の知っている限りこの試みは何度も失敗している。

これまで何度も、ロリエロ絵のイラストレーター達は「Twitterではやってられない! Pawoo(Pixiv運営するMastodonインスタンスTwitterに似ている)に移住しよう!」と発言しているのだが、まあ十中八九失敗している。

なぜかと言えば、Pawooはユーザーが圧倒的に少なく、絵を多くの人に見てもらえないからだ。

クリエイターにとって知名度こそ全てだ。知名度だけ高ければいいわけでもないが、知名度がなければ何もできない。そして、それはロリエロのイラストレーターも例外ではない。

というわけで、結局彼らは絵に修正を入れたりリンクを貼ったりして、だましだましTwitter活動し続けている。

とまあ、ここまで書くと「そんなもん描くやつ勝手にくたばればいいだろ」と思う人が多数派だろう。

まあその通りなんだけれど、ちょっとだけ待ってほしい。

上で書いたとおり、ロリエロ絵の最大の問題は「見たくない人の目に入る」ことで、それさえ無ければ被害者はいなくなる。

からゾーニングさえ上手くできれば(ほぼ)問題はないのだ。

ではロリエロに限らずweb上で、「見たい人にはちゃんと届くように」「見たくない人には届かないように」上手くゾーニングするにはどうすればいいんだろう。

私は「webブラウザ検索エンジン提供する企業が、最初ユーザーに見たくないもの選択させ」、「Twitterなどのサービス提供者が連携する機構を作り」、「投稿者がきちんとカテゴリ選択して投稿する」ことでしか解決できないと思っている。

例えば、Google Chromeブラウザ)のインストール時、ユーザーに「ポルノ」「暴力」など見たくないもの選択させる。

Twitterはそれに対応するカテゴリ選択肢を作り、投稿時などに選択できるようにする。

そして投稿者が「ポルノ」にチェックをつけて投稿すれば、ポルノを見たくない人には届かないといった寸法だ。

そして、これらのルールを破ったユーザーサービス提供者には即座にペナルティを課すようにする。

大仰なやり方ではあるが、web上のゾーニングロリエロだけでなく大きな問題なのでこれくらいやってもいいんじゃないかと思っている。

そして、この仕組みを作れるのは世界中のwebを席巻しているGoogleくらいじゃないだろうか。

…というわけで、Googleさん、そろそろ(誰も不幸にならない形で)ゾーニングに本気出してください。

お願いします。

はい

これが言いたかっただけ。

2019-03-31

長い旅路

2017-04-13

b:id:shields-pikes

マストドンについて、ブログ書きました。あと、今日このあとからオフ会やります

2017-04-13

b:id:shields-pikes

今夜4/13、アーガイルオフィスmastodonオフ会やってるので、気軽に寄ってねー。酒は無料です!

夕方に呼びかけて夜に来てくれる人のありがたさよ。10人以上のおっさん達で超盛り上がった! またやります

2017-04-14

b:id:shields-pikes

優れた記事中央集権化と分散化の流れは、振り子のように行ったり来たりするもの。今後しばらくは分散化の方向なのかもね。でも、mstdn.jpの例のように、おそらく自動的一極集中が進む気もする。

2017-04-15

b:id:shields-pikes

こんなんプロトタイプだろ。ニーズがあって注目されれば、ソース構造もどんどん改善されて行く。まず、情報インフラTwitterじゃなくてもいいんだ、自分でも運営できるんだ、ってことが皆に浸透したこと画期的

2017-04-15

b:id:shields-pikes

これは非常に正しい。自前の鯖を立てることにしよう。

2017-04-18

b:id:shields-pikes

このインスタンス状況まとめページは役に立つ

2017-04-20

b:id:shields-pikes

マストドンは愛すべきサービスだが、今のままではとても流行るとは思えない。「インスタンスを選ぶ」の時点で、一般人の8割が脱落する。例えばLINE最初サーバを選んで始める仕組みなら、こんなに普及してないよ。

2017-04-21

b:id:shields-pikes

今こそ、新しい個人インスタンスを立てて、企業色を嫌うユーザー達を取り込むチャンスだー!!

2017-04-30

b:id:shields-pikes

マストドン流行ってます、とか語りつつ使ってなかったり、使わずに大したことないとか言ってるWeb業界人が本当に意味不明インスタンス運営知識覚悟必要だが、1分で出来るユーザー登録を何故やらないのか。

2017-11-12

b:id:shields-pikes

Mastodon別に「来て」はいないだろう。一部コミュニティで、ツールとして定着してるかもしれないけど。

2017-12-02

b:id:shields-pikes

俺は、国内最初Mastodonオフ会を自社オフィスで開いて以来、Mastodon会議に参加してヌルカル氏、清水氏、江添氏その他の話を聞くまではヘビーユーザーだったが、これはスケールしないな、と確信したので常用を辞めた。

2018-05-10

b:id:shields-pikes

アカウントの完全削除処理って地味に影響範囲が大きいかほとんどのサービスは利用凍結くらいで止めてるんだけど、マストドンで実行すると他のインスタンス横断のデータ処理になるので、マジで恐ろし過ぎる。

2018-09-18

b:id:shields-pikes

はてブ投稿連携ができたら、もっとMastodonも使うんだけどなー。俺にとってNo. 1のソーシャルメディアは、はてブからなー。

2018-10-17

b:id:shields-pikes

これは乗るべきか乗らざるべきか迷うなあ。GAFA以外の次世代の有力サービスが軒並み参画して流れがこっちに向けば普及するかもしれないが、そうでなければMastodonレベルだろう。とりあえず仕様確認してみよう。

2019-03-28

b:id:shields-pikes

当時からMastodonの行く末を予想してツイートしてたが、予想通りすぎる。結局、スケールできないSNSは廃れるんだよ。どう考えても、10万以上のユーザーを抱えるにはコスト的に見合わない。

2019-03-26

anond:20190326163127

作品概念(クラス的なもの)」と「実際の作品(インスタンス的なもの)」を混同してはいいか

賞味期限」というのは「労力に見合った成果か?」とも言い換えられる。

短期的な売り上げだけを考えて、安易エロ萌えに頼れば長期的なリターンを得られない。

2019-03-25

anond:20190325152922

しかしたら最近の人はバトロワMMOではない事が理解できんのかもしれんな。

あれらはいわば、1ルーム100人くらいのMOFPSで、マッチごとにマップインスタンス作成される形なんだけど、

そういうゲームしかしてないとMMOの「世界が一つしかない」という感覚が分からないのかも。

MMORPGも多サーバー化に加えチャンネル制が当たり前になってきて、それが理解を妨げている可能性もあるし。

Stadiaの開発者インタビュー その2

やっぱり途中で切れたので続きから


サービス提供を開始します。

するとシステムの準備は万端で、必要ソフトウェアの開発が必要ということでしょうか。Microsoftを見ますと、彼等はXBox OneのHWをサーバラックに積んでいるようです。あなたがたの手法とは異なりますか?

違います

するとGoogleインフラバックエンドのみでなくソフトウェアにも投資を考えていますか?

そうです。

自身の開発スタジオも考えていますか?

はい。Stadia Games and Entertainment組織を発表しました。これは我々の1stパーティスタジオです。

それが今起こっている?

はい

Google開発者に対し全てのツール支援しています。Stadia向けの開発は彼らにとって別のターゲットしか過ぎません。Visual Studioを用いる既存ツールや彼らが用いるツールの全てと共に、彼らのワークフロー統合されます。従ってStadia向けの開発はPlayStationXbox向けの開発と同じくらい簡単です。

我々はUnrealサポートします。UnityがStadiaサポートします。予想される多種多用な業界標準ツールミドルウェアが準備されます

意地悪な質問します。Googleコントロールを超えたものがありますよね。特にユーザサイド、クライアントサイドのインフラ家庭内安価ルータです。このような問題をどのように解決しますか?

とても良い質問です。我々はユーザに対し彼等のインフラの中で何が起こっているかをできる限り理解できるよう支援する必要があります。また我々はゲーマーに対し最適な体験を得られるようなチューニングを行うことが可能情報に対し投資を行うだけでなく、我々自身技術を用いて最良のパフォーマンスを実現するつもりです。Google技術の多くがインターネット網の基盤であることを思い出して下さい。我々はDCから情報がどのようにユーザに届くかを良く理解しております。できる限りの最適化を行うつもりです。

デベロッパパブリッシャは既存ゲームをStadia移植できるのですね。しかし同時にGoogleは新しい選択肢も数多く提供できると

その通りです。それこそが我々のプラットフォーム根本的な差別化ポイントです。既存ゲームカタログを持つデベロッパにとってStadia簡単で親しみ易いものです。我々はできる限り摩擦なくゲーム移植を行えるようにします。なぜならゲーマーは好きなゲームを遊びたいですし、彼らの愛するキャラクターストーリー世界を楽しみたいのです。しかし我々はまた開発者未来を描く新しいキャンバスをも提供します。ゲームを高速に配布し、プレーヤーと新しい手段で、特にYoutubeにて繋げます。そして開発者が持つアイデアを実現するための前例の無い技術提供します。


これまでのクラウドシステムクライアントサイドの限界基本的に画質やレイテンシに起こりました。明らかにこれらの問題インパクトはここ数年で新たにより良い技術を得ることとインフラ改善されることで緩和されてきました。しかローカル品質ストリーミング品質との間には今でも根本的なギャップ存在します。私はidソフトウェアZenimax特許を見たのですが彼らはh.264のモーションベクター効果的に用いてクライアントサイドのある程度の予測を立てレイテンシの知覚を減らしていました。Project Streamにも測定可能レイテンシ存在します。ギャップを閉じるために何をしていますか? これらの問題解決されたでしょうか。それとも少なくとも緩和はされましたか

解決されたと同時に緩和されています。まずデータセンターに対しより多くの人々がより良い経験を得られるようにするための投資が行われました。また圧縮アルゴリズムについては我々に抜本的な先進性が存在します。Google圧縮アルゴリズム標準仕様先駆者でありこの点がストリーミングの将来をより確実にします。残念なことですがGoogleでも制御できない点が光の速さです。そのためこの点が常に要因となりますしかし常に理解しなければならないこととして、我々は常にエッジ(終端)にもインフラを構築していることが挙げられますGoogleの中心にある巨大なデータセンタだけではありません。我々はできる限りエンドユーザの側にインフラを構築しています。それによって歴史上の幾つかの問題回避することが可能です。さらにまだ率直な、あまり洗練されていないProject Streamのストリーマーでも信じられない結果を出していますさらに我々はサービスリリース時に1080p60を超える品質を実現できるだけの根本的な改善を行いました。我々は8Kに至るでしょう。

それは素晴しい。それらの改善は全て圧縮に関連するものですか?

圧縮ネットワークです。我々はGoogleインフラに投入した数々の改善点に依っています。BBR、QUIC、WebRTCを基盤としてその上に構築がなされました。だからIPパケットの低レイテンシでの配信だけでなく、送信元へのフィードバックも行うことが可能です。ですのであなたが仰るZenimax使用した技術なら、彼らはここでも利用することが可能です。彼らは彼らのゲーム最適化を行うことができるでしょう。我々はフレーム毎のレイテンシ予測可能で彼らにそれに合わせて調整を行わせることができます


入力を受け取って、ゲームロジックを処理して描画を行うと、60Hzのゲームでは50ms程になります。続いてエンコード転送デコード、表示を行うとストリームではPC上のゲームに比べさらに60ms程かかります。これを改善することはできますか?

我々は改善を続けますStream最初バージョンです。我々は性能向上のために調査を行っており、レイテンシ適応していきますリリース時にはより良くなっているでしょう。

クラウドシステム接続可能性に従って成否が決まります。例えばRed Dead Redemption 2を数万、数十万、場合によっては数百万のプレーヤーオンラインにて同時に立ち上げるとします。システムの成否はアクセスによります。もしゲームプレイできないなら重大な障害となります

かにそのとおりです。そしてそれこそがGoogleが何年もかけて開発してきたスキルであり、抜本的なスケールする能力です。我々がどうやって実現しているのか、何をしてきたかについては今日は詳細にはお話しません。しかGMailMapYoutubeが同時に利用可能であるためと同じ基本的技術のいくつかが我々が依るものです。


我々は現在、現行世代が終了する移行の時を迎えています。これまではコンソールベースラインを定めてきました。Stadia次世代XboxPlayStationに対抗できると考えますか?

我々は競合他社が何をしているかは存じておりません。

でもGoogleには良い予測を立てられる優れた人々がいますよね?

我々の第一世代システムに導入されるGPU10Tflops以上の性能があり、さらスケールアップしま

GPUユーザ間で共有されますか? それとも1人のユーザが独占しますか?

単一インスタンスです。

NVIDIAGPUですか?

AMDです。

カスタムGPUだと思います

カスタムGPUです。

Google要件のために作られた訳ですね。他にも公開できる情報はありますか? Vegaですか? それともNavi、もしくはさら新世代ですか?

情報を公開したくない訳ではないのですが、このプラットフォーム進化することのほうがより重要です。そしてこの進化ユーザ開発者の双方に対しシームレスに行われることを確認して頂きたいのです。そして進化は常に継続し、誰もが常に最新で最高の物を手に入れます

クラウド確約する点ですね。ユーザはHWをアップグレードする必要がないと。

開発者にもこのように考えて欲しいのです。もちろん完全には抽象化されていません。特にゲーム開発者にとっては。しかし我々はそれでもこのプラットフォームが常に進化していると考えて欲しいのです。速さや容量、リソースには制限されていないのだと。

AMDGPUを使うことでStadiaと他のコンソールの間に共通な点ができました。開発者にとって利益となるでしょうか?

シェーダコンパイラツールをいくつか開発しました。これらは開発を楽にするでしょう。しか現在GPUはとても優れており開発者が既にVulkanに親しんでいれば、例えばid Softwareさんは既に全てVulkanに移行していますが、そのような開発者の方々には既存ゲームをStadia移植するのはとても簡単です。Doom Eternal4K、60フレームで動いでいるのは既にご覧になったと思います。非常に素晴しい状態です。これこそが我々にとって重要証明ポイントです。FPSグラフィックプレイアビリティの双方で要求が高いゲームです。 従ってこれは我々のプラットフォームの強力な証拠であり、idさんにも講演して頂きます

CPUについては何か公開できる話はありますか?

x86で2.7GHzで動作しています開発者にとり慣れのあるものです。開発全体を通して、CPUは制約となる要因ではありません。我々は全てのタイトル動作するに十分なCPU提供します。

コア数、スレッド数は?

沢山です。

8コア、16スレッド? それより多い? 少い?

公開できない情報です。ハイパースレッド使用しています

しかサーバ級のCPUです。Stadiaはこれまでのコンソールと違いパッケージングに制約を受けません。熱対策問題も異なりますコンソールとはサイズパッケージング動機が異なりますデータセンタの中でそれはとても汚なく見えるかもしれません。一方でとても帯域幅が高いメモリ使用可能で、とても高速なペタバイト級のローカルストレージ使用可能です。ご家庭のコンシューマデバイスよりも数百倍は速い物です。

するとそれが開発者が全く異なる体験のために利用可能な要因となる訳ですね。得られる機会はとても大きいことでしょう。しかし我々はマルチプラットフォーム時代生活していますGoogle先進的な機能は1stパーティのみが利用できるものですか?

パートナーには彼らが話せる時点で彼らの計画を教えてくれるよう伝えています。Stadiaをこの世界で最も偉大なゲーム開発者達に説明することにはとても興奮します。Stadiaは、開発コードではYetiと呼ばれていましたが、Stadiaビジョン説明すると、開発者リアクションは「これは私が期待したもののものだ。これはまさに我々の次のゲームのためのビジョンのものだ。elastic computingの考え、次世代レベルマルチプレーヤー環境ゲームを観ることと遊ぶことの境をあやふやにし1つの体験にすること」と話されます

イノベーションの1つの領域として、最初のほうで述べましたが、マルチプレーヤー環境において、単純にパケット複数プレーヤーリダイレクすることから原子時計レベルでのコンシステンシーを全ての状態遷移において定期的にクライアント間で更新する真のシミュレーションへの移行が挙げられます。これにより開発者はこれまでには不可能だった分散された物理シミュレーションを得ることができます。これだけでもゲーム設計イノベーションに対し大きく寄与します。このため多くの開発者が、大袈裟でなしに、実際にとても感動的なリアクションを我々のプレゼンに対して返して下さっています


多くの問題解決し、規準を上げる可能性がある訳ですね。

これこそがゲーム業界の素晴しい点です。技術が常に創造性を刺激し、ゲームに対しより大きな聴衆を作り、そのことがプレーヤー開発者に対しより大きな機会を作ってきました。エコシステム進化し、正の方向に回り続けるなら、それはゲームを遊ぶことにとって良いことです。

あなたは先程、スケーラビティとStadiaがどのようにしてより多くのリソースを立ち上げ増大する要求対応するかについて話して下さいました。しかし、同時に10TflopsのGPUサーバクラスCPU存在するとも仰いました。リソース拡張をどのように行うのですか?

3台のGPSが一緒に実行されるデモを行っています。私は上限が無いとは申しません。しかし我々は技術上の限界を上げています。そしてStadiaは静的なプラットフォームではありません。このプラットフォームは5年や6年の間、レベルが変わらない訳ではありません。開発者プレーヤー要求に従い、成長し、進化するプラットフォームです。なぜならStadiaデータセンタの中に構築されています進化させるのは我々にとって簡単なことです。

ここまで第一世代について多くのことを教えて頂きました。すると第二世代やその後の世代もあるでしょう。現状でもスケールアップできるわけですが、3台のGPU連携次世代でも可能ですか?

CPU/GPU/メモリ帯域幅の変更にはいくつかの自然な段階があります。これは家庭の物理な小売の端末よりももっとスムースでより継続的な進化です。しかし、より重要なことは基盤データセンタ網とそれに含まれネットワーク技術への投資です。この2つが一致して行われることが重要でどちらか1つではダメなのです。

先程、エッジ上のインフラについて触れられましたが、例えばNetflixISPキャッシュインストールしている状況があると思います。これがGoogleが行っていることですか? それとも既にYoutubeで行われていますか?

それは我々も既に行っていますGoogleが既に20年以上、行っていることです。我々が依って立つまた別の巨人の肩です。


Project Streamではユーザに対し最低で25Mbpsの帯域幅要件しました。これはストリーミングのみのためですか? それとも他のユーザが同時に同じインスタンス接続する場合を含みますか?

我々はStreamさらに強化させています。従ってユーザはこの制約が全体のスタックに対する改善最適化、また特に時間によって緩和されることを期待するでしょう。我々はその期待の上を行きます

4K60には相当の帯域幅がいるのでしょうね?

4K60はもちろんより要求が高くなります

1080p60は低くなる・・・

私は具体的な数値についてはコメントしません。しかし当然低くなります

インターネット接続環境はStadiaリリースする市場では全体的に上昇機運が見られます。つまりこのパフォーマンス特性ますます多くのユーザが利用可能になります

さらに繰り返しになりますが、BBRを初めとする我々の技術がありますさらに覚えておいて頂きたいのは我々のネットワークに対する理解そのままではありません。それらもまた時と共に改善されていきますYoutubeマクロ

Stadiaの開発者インタビュー

Eurogamerにより独占配信されたStadia開発者二人に対するインタビュー記事

https://www.eurogamer.net/articles/digitalfoundry-2019-google-stadia-phil-harrison-majd-bakar-interview

やっつけなので可能なら原文を読むことをお勧めします。

---

なぜ今なのでしょうか?

タイミング問題です。20年間の蓄積によりGoogleにはデータセンタ内のパフォーマンスに優位性が存在します。Googleデータセンタ内ではHWメーカーです。我々はデータセンタ内で何年もの間、高い性能で端末間を接続する基盤を構築してきました。Youtubeでの経験からプレーヤーサイドの観点からだけでなくデータセンタ内部から技術観点から技術統合を行ってきました。他社でもその視点存在していますGoogleにはその点に固有のアドバンテージ存在します。

これまでの箱をTVの下に置いておいたパラダイムに比べ、無限演算リソースによる可能性が現れます。これまで存在しなかったことをできる可能性があります

その通りです。我々にはレガシーがありません。全てが21世紀のために設計されています開発者制限の無い計算資源が利用でき、何よりもマルチプレーヤーサポートできます。これまでのマルチプレーヤー環境は一番遅い通信に影響を受け開発者は最も遅い接続に対し最適化必要でした。我々のプラットフォームではクライアントサーバも同じアーキテクチャの下にあります。これまではクライアントサーバの間のping支配されていましたが我々の環境なら最速でマイクロ秒で済みます。だからプレーヤーの数は単一インスタンスにて動的にスケールアップが可能です。バトルロイヤルなら数百から数千、数万のプレーヤーが集まることも可能です。それが実際に楽しいかどうかは置いておくとしても、新聞ヘッドラインを飾ることが可能技術です。

クライアントサーバの双方でこの利益を得られるのでしょうか

両方です。

すると開発者に対しStadiaホリデーシーズンにぴったりの最高の製品だと言えると。理に適った範囲無限計算資源が得られると。

ユーザが我々のプライベートLANからはみ出さないだけでもその効果は大きいものです。Googleは45万kmに及ぶ光ケーブルにより世界中データセンタ間を接続しています米国西海岸から東海岸まででも20ms、フランクフルトからマドリッドでも20ms。これにより開発者は最も極端な場合においてもレイテンシ予測可能でそれに従い設計を行うことができます


Youtbeとの統合について教えて下さい。

StadiaYoutube技術と深く結びついていますが、実際には一歩引いています今日ゲーム業界を考えてみて下さい。2つの世界共存しています。1つはゲームプレイする人々で、もう1つはゲームを見る人達です。2億人の人々がYoutubeゲーム毎日見ています2018年には述べで500億時間ゲームを視聴するのに費されています時間人口の双方で信じられない程の視聴が存在します。我々のビジョンはこの2つの世界を1つにすることでゲームを見ることができ、かつ、プレイもできる、双方向に楽しめることです。

まり重要なのはゲームシステムでもなくコンソールでもありません。噂とは異なり我々はコンソールビジネスには参入しません。我々のプラットフォームの要点はコンソールでは無いことで、皆が集まる場所を作ることです。我々は箱でなく場所を作る。今までと異なる体験を得られる場所です。ゲームを見るなり、遊ぶなり、参加する場所であり、かつユーザが楽しむ場所であり、ユーザ他人を楽しませる場所です。

から我々のブランドはStadiaといいます。これはスタジアム複数形です。スタジアムスポーツを行う場所ですが同時に誰もがエンターテイメントを楽しむ場所でもあります。だから我々はそれをブランドにしたかったのです。皆が遊んで、観て、参加して、さらにはゲームをする場所。一歩下がって見ることもできる場所。常にどのボタンを押したか意識しないでも良い場所。他のアーキテクチャでは実現できない場所です。

まりリアルタイムシミュレーションゲームで全ての駒が人々であるようなものですか?

その通りです。そして単純に技術的に深い点を求めて、我々は第一世代でも4K60fpsHDRサラウンドサポートしました。さら開発者必要インフラに従ってスケールします。それだけでなく、同時にYoutubeに常に4K60fpsHDR画像送信することが可能です。だからあなたゲーム体験の思い出は常に最高の状態になります

Googleは全てを記録するでしょうか?

プレーヤー次第です。Googleは全てを記録はしません。もしプレーヤーが望むならGoogle4Kストリームしま

共有が友達だけか、世界中に公開かも自由選択可能です。Googleユーザ制御を明け渡します。もしユーザYoutubeで公開すれば誰でもリンククリックすることでそのゲームを遊ぶことができます

するとユーザshareするだけで誰でもがその特定ゲームに参加することができる訳ですね。

そう。そしてこれはマルチプレーヤーゲームロビーの新しい形となりますYoutubeクリエイターなら誰でもがファンチャンネルのsubscriberを自分ゲームへと誘うことができます生主として、Youtubeクリエイターとして私は視聴者を私のゲームに瞬間的に招待できます。それが私と10人の友達でも、(訳注: セレブの)Matpatと彼の数百万の購読者でも、技術は同じです。

アカウントシステムベースYoutubeですか?

Googleアカウントの一部です。従ってGMailアカウントがStadiaへのログインに利用できます。他の基盤についても説明させて下さい。最初サービス立ち上げから全ての画面への対応を行いますTVPCラップトップタブレット携帯です。我々のプラットフォームの基本は画面に依存しないことです。これまで40年間、ゲーム開発は端末依存でした。開発者として私は制約の範囲内で、私の創造性を開発対象の端末に合わせてスケールダウンする必要がありました。

我々はStadiaでそれを逆にしたいのです。我々は開発者に対し彼らの考えをスケールさせ、どの端末の縛りから解放したいのです。パフォーマンスに優れ、リンククリックすればゲームは5秒以内に開始されますダウンロードもなく、パッチもなく、インストール必要なく、アップデートもありません。多くの場合、専用のHWも必要がありません。従って古いラップトップChromeブラウザ使用する場合にでも皆さんが既に持っているだろうHID仕様に準ずるUSBコントローラ動作します。そして、もちろん、我々自身コントローラも開発中です。

なぜ独自コントローラを作るのですか? USBコントローラはどこにでもあるじゃないですか

コントローラ自作する理由はいくつかあります。1つはTVへの接続です。我々はChromecastをストリーミング技術採用します。Stadiaコントローラの最も優れた機能の1つはそれがWiFi接続DC内のゲームに直接接続することです。ローカルデバイスとは接続しません。

それは面白い。するとほとんどそれ自体が端末な訳ですね。

その通りです。これこそが我々のブランドの実現であり、具現化です。そして独自コントローラにより最高のパフォーマンスが実現します。ゲームに直接接続するためにプレーヤーは画面を移動することが可能です。プレーヤーはどの画面でも自由に遊び、停止し、他の画面でゲームに復帰することが可能です。

そしてコントローラには2つの追加されたボタンがあります。1つはGoogle Assistantの技術マイクを用いますユーザ選択により、ユーザプラットフォームゲームの双方に対し、自然言語を用いて会話が可能です。例えば「Hey, Google。MadjとPatrickと一緒にGame Xをやりたいな」と言えばStadiaマルチプレーヤーゲーム指定した友人と共に直ぐに開始します。

するとGoogle伝統的なUI回避するのですね?

我々はゲーマー可能な限り素早くゲームに辿り着かせるよう考えています。数多くの研究を行いましたが、多くのゲーマーゲームを起動したら直ぐに友人とゲームを開始したいと考えていますゲーマーUI時間を費したくは無いのです。

誰かが言ったことですが、現在コンソールは起動した時にまるで仕事のように感じると言うのです。ゲーム自体更新や、ゲーム更新があります。我々はそれらを完全に取り除きたいと考えています。もう1つのボタンは、ちょっと趣が異なるのですが、Youtubeシェアできます

端末は何でも良いのですね? スマホスマートTVも?

Youtubeが観られるならどこでもStadiaは動きます

TVへの接続にはChromecastが使用されると。では実際にはどのように動きますか?Chromecastがスマホラップトップからストリーミングを受け取るのでしょうか?

Chromecastはスマホからストリームを受取はしません。Chromecastはスマホから命令のみ受けます画像NetflixYoutubeから直接受け取ります。Stadia場合、StadiaコントローラからChromecastへとこのゲームインスタンスへと接続せよと命令がなされ、Chromecastはゲームインスタンスから動画ストリームを受け取りますクライアントはとてもシンプルです。行うのはネットワーク接続ビデオと音声のデコードのみです。Chromecastは入力を処理しません。全て入力コントローラが扱いますビデオと音声とネットワーク接続Chromecastの基本動作で全て既に組込まれています

Stadiaの起動はどうするのですか? コントローラで?

そうです。とても良く出来ていますWiFiに繋ぐだけです。コントローラにはWiFiIDとPWを入れるだけです。それだけです。ホームボタンを押すと勝手Chromecastを探し直ぐにChromecast上でクライアントを起動します。UIが表示され直ぐにゲームを遊ぶことができますデジタルパッドでUI操作することも可能です。これが重い処理を全てクラウドへと移行する点の美しさです。Chromecastのような低消費電力の端末で説得力のある体験ができますChromecastは5W位下です。Micro-USBで給電可能です。典型的コンソール100から150Wもします。またこれまで説明しませんでしたが、例えスマホでも行うことは動画再生だけです。従ってAssassin's CreedDoomや他の重いゲームあなたスマホの上でモバイルゲームよりも低消費電力で動作します。だからスマホ10時間でも遊べます

スマートTVではStadiaYoutubeクライアントに組込まれるのでしょうか。それともStadia独立して起動させますか?

今の所、我々はChromecastのみに集中しています。でも技術的、機能的な観点からYoutubeがある場所ならどこでも動きます。我々はまだStadiaをどのようにユーザに届けるかは検討中です。

コントローラに話が戻りますが、モバイル端末にはやはり物理的なアタッチメント必要に思われます。例えばスマホコントローラ接続するような。MicrosoftのXCloudを見ていると操作には実際に問題があるようです。

Googleには解決手段があります

そうでしょう。スマホコントローラ取り付け以外にも、明らかな解決手段としてSwitchのようなクライアント端末を作るのでしょうか?

サービス開始時から提供されるサードパーティによる解決手段サポートしています。他にもアイデアがありますしかし今は話せません。

なるほど。GoogleUbisoftデモを行いましたが、これまでにDoom 2016でもデモを行いました。他にも開発企業はありますか?

良い質問です。私がこのプロジェクトに参加する前からチームは既に何社かと提携しここ何年かの間に技術提供していました。StadiaLinuxベースです。グラフィックAPIはVulkanです。開発企業クラウドインスタンス作成しますので、開発キットも今ではクラウドにありますしかクラウドだけでなく、開発社のプライベートDCでも、机上のPCでも可能です。

すると開発者物理的なHWを持つことが可能ですか?

もしそうしたいなら。でも我々は今後のトレンドが開発でも配布でもますますクラウドへと移行していくと考えています。従って今後数年で開発者にとってクラウド中心、クラウドネイティブゲーム開発での標準となるでしょう。

どの企業自身クラウドシステムを開発しているように見えます。例えばOriginクラウドがあるでしょう。しか必要とされるインフラ要件は、我々がここで話しているような内容を達成するには、3rdパーティには荷が重いように思えます。彼らは自身クラウド継続しながら、Googleシステムを導入するでしょうか。

デベロッパーパブリッシャーはとても賢くクラウドネイティブとなる新しいゲーム体験を達成するために必要ツール技術について考えていると思いますしかしそれは世界中で何千ものアクセスポイントを持つデータセンターを運営することや、それらの運営必要な莫大な投資資本とは異なるものです。Googleは今年単年でも$13Bの資本を投下しています

それはとても巨額ですね。しかしそれでも依然としてシステムを構築しインストールするのは根本的な問題です。多分野に渡る段階的なロールアウトになるのでしょうか?

米国では全ての必要場所に展開が終わっています。Project Stream試験必要環境2018年末には整いました。我々はGoogle社内で、Google社員対象2017年の始めから2年間の間、プライベートテストを行ってきました。2019年には米、加、西欧、英にて Permalink | 記事への反応(1) | 06:10

2019-03-16

機械エンジニア独り言

ソフト屋の、「俺たちITエンジニアだぜ!?IOTプログラミングクラスインスタンスクラウド最高だぜ!?」感が苦手なので全員とっとと死ねば良いと思う。あはは物理数学ちゃんとやったことないでしょ?ネットから似たコード探してコピペしていっちょ前な顔してハード屋なんて時代遅れですよ。これからソフトですよ。俺たち、希少価値の高いエンジニアから引く手あまただぜ!?ってゆー。本当に死んで滅びてくれ。

2019-03-01

anond:20190301130236

社会的常識形成エビデンスで求まるものではないし、

単一の巨大なインスタンス対象なため同条件で実験も立証も難しいのだから

エビデンスもなしに、一部のカルチャーを「社会的常識に反する」と弾圧することが、どういう結果をもたらすか君は歴史に学ばなかったのか?

民主主義的な国家システムを現状最もマシな意志集約の結果としてみなせば、

現行法がそうなっているという点をもって、ひとまず妥当社会的重要性の現状認識になるんじゃないかしらね

その現行法を超える規制を求める以上は、「妥当社会的重要性の現状認識」に背いてるということになるが?

新たな現状認識を作ろうとする癖に、根拠もなく他者人権を踏みにじるのか?

そして何度も聞いてるが、いつフェミポリコレ価値観民主主義手続きを得た社会的合意になったんだ?

どの選挙の争点になった?どの法に定義された?

そもそも具体的ボーダーラインもないものについて何を言ってるんだ?


もちろん異論は多々あるのでしょうけども、

エビデンスが無いからそうでは言えないという反論の仕方が悪手になるのは、

そもそもエビデンスが出しにくい実社会という一つのコンテクストの結果である社会問題だからでしょう。

エビデンスが出しにくい、出せないならあきらめるべきなのだ

あやふや根拠他人を黙らせる権利。そんなものがあるのか。誰に!?


でも、対等関係である同性愛保護対象となる児童という違い等、相違点も多いので同じ結論には至らない気がするよ。

児童保護対象」「性交は加害」こういうのってただの「価値観」であって「真理」ではないよ?

そして児童性愛が気に入らないなら、ナチ弾圧された共産主義者ユダヤ人を例にとってもいい。

あの時代あの国の「民主主義的正解」「社会的常識」はナチとともにあったわけだ。

そのナチが、エビデンスなく「劣等」と決めつけた者に何をしたか知らないわけじゃないだろう?

今またエビデンスなく、「社会的常識」だの「悪影響」だのと一部のカルチャーレッテルをはり、ゲットーに追い詰めるのか?

答えろよ。

2019-02-20

anond:20190220112213

カウンターとしてのOSSという切り口だと

かなり成功してる部類に入るよね

メインストリームが耐えきれない程の邪悪になってからホコリ被ってるのが掘り起こされるとかじゃなくて

今も大規模実稼働インスタンス運用され知見も蓄積されている

2019-02-19

マッサージ好きが明確なビジョンを打ち出す新井浩文のインシデントについて

意識の高いおれはマッサージがアグリーだ。いわゆるメンエスと読み取れるやつな。

電話リザーブしてコンドミニアムの一室に働き、女性が出迎えてくれる。

お茶とかだしてビジネス成功させてくれたり、世界中の貧しい子供たちをいつか助けようと思ったりしてな。

そして、定時で退社した後シャワーを浴びてマッサージする。

足掛かりとしてはうつぶせハイヤーアイビー・リーグからだ、温かいオイルバーニッシングし、カルフを撫でる(笑)

そのバッチ処理もも。内ももを触り、Macを広げ、ビジネス書を読みながらカーソルアスタリスクアリーを撫でる。

現在の情勢におけるあとは”グルヌイユ足”だ。これメモっといた方がいいよ。足をまげてセラピさんが腕とパームを使って鼠径カンパニークリーンアップしてウェイストする。

手がアソコに当たるか当たらないかグレーゾーンのTRIZを駆使して導き出したところ。既にビンビンにコンセンサスを得ている───。

そのペンディングは四つん這い。四つん這いのコンディションで後ろからハンドツールを回してくれて鼠径協同組合を流す。

息が荒く携わるのを止められない。はぁはぁ日々成長。日々成長。日々成長。日々成長。日々成長。

漸く仰向けだ日々成長。日々成長。日々成長。日々成長。日々成長。

ここ(西海岸)で「ある」場合と「ない、それに私はこんな所でくすぶる気はない」場合が起こりうるんだ。

そのときまで欧米では通用しないと思うよ、それはわからない。

ジョブズに倣えば「雰囲気ある」場合に「より非常に意味がある…ここまではいいよね?」オケーションがごくまれにある。

この案件スティーブ・ジョブズの体内に潜む俺たちメンエスグリーホームランと言ったり、難病に苦しむ子供たちに頑張るよう鼓舞したりさせて頂きますんだ。

だな、新井浩文あくまでもこのビジネスチャンスは受け身でなければならないんじゃなくて、あえてやらなかったんだ。

しゃべりでの交渉トレンド入りしていいものの、無理やりなんてもってのほか

存在することないこと、メンエスでのMECEはセラピストによってプレゼンしられるものなんだよ。って言ってもわからいか

「ねだるな、勝ち取るな、さすんば与えられん」

弊社がモテるインスタンスモチベーションに溺れ、セラピストに企業合併をもとめるなんてマッサージマッチングの風上にも置けないよ。

大いに反省、というか自己嫌悪してエラーを償って下さりますようお願い申し上げます

2019-02-10

盾の勇者がひどい(ネタバレ

うわー。一話でかなり辛い。

女性上位とか言ってる割には国王大臣、そのた商店主とか全部男だし

女性に酒を勧められたら男は普通断らない」

可愛い女の子飲食店でおまけしてもらえる」

強姦罪未遂でも極刑

あたりが女性上位の描写としてでてきます

なんとなく作者は痴漢問題で「まず痴漢冤罪問題だ!」とか現代日本レディースディなどを根拠に「女尊男卑男性差別社会」とか真顔で言ってそうでドン引き

で、強姦冤罪でひどい目みたし、盾の勇者攻撃カスなので仲間いないときついのに強姦冤罪のおかげでまともなのは仲間にならないので人身売買でタヌキ耳の亜人少女をゲット。

うわー。キッツー、キモー。

と思ってたらほぼノーダメジの雑魚的が自分を噛んでる間に攻撃しろ!とか嫌がるのにやらせます普通虐待ですありがとうございました。

で、タヌ耳少女の親を殺したのと同種の魔物を同じ要領で殺させてトラウマ克服!

なんか、アレですね。猫嫌いを克服させようと猫穴に放り込んで閉じ込めたら、猫嫌いが治っちゃう世界なんでしょうね。

原作者ボートだったかなんとかスクール体罰教育根性論を賛美するような人じゃないか心配です。

でそのタヌ耳奴隷が開放されても主人公なついてる描写肯定的に描かれてて、逆に人身売買はいかんだろという人間愚か者って感じです。

19世紀どころか21世紀に、「良き奴隷主」と「良き従順奴隷」が賛美される作品メジャー作品として作られていることにあるしゅのセンス・オブ・ワンダーを感じます

なんか日本奴隷人身売買を大して悪いと思ってない人が多いんじゃないか?という危惧現実だったらどうしようかと思う所存です。

一話で強姦冤罪をデッチ上げた女性は実は王女だった、と言われてもなぜそんなデッチ上げをしたのかさっぱりわかりません。

亜人差別されてるという描写があったのに、町の人がタヌ耳奴隷には食品などをおまけしてあげるという好意的対応いまいちわかりません。

なんというか設定というか人物の造形もそのばその場のインスタンスな役目だけで前後脈絡とか気にしてないのかもしれません。

作画音楽声優の演技などはいいだけに根本的な設定ストーリーダメさが鼻につきます

まあ、悪いのは原作者というよりこれをアニメ化にゴーサインした人なんでしょうが

2019-01-10

元号修正ってそんなに難しいの?

DBに格納してある時間元号情報普通含まないじゃん。

ということはDBから取り出したtimeインスタンスがあるとして、time.year()の値から今が平成何年かを作り出すtime.era()みたいな関数をどこかで作るはずじゃん。

そのera関数修正して、あと新しい元号の値からtimeインスタンスを作るための入り口を設けるだけで済むと思うんだけど。どういう設計だと元号修正が難しくなるの?

学者なので教えてください。

2019-01-03

anond:20190103184241

// WindowsProject7.cpp: アプリケーションエントリ ポイント定義します。
//

#include "stdafx.h"
#include "WindowsProject7.h"

#define MAX_LOADSTRING 100

// グローバル変数:
HINSTANCE hInst;                                // 現在インターフェイス
WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーテキスト
WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名

// このコード モジュールに含まれ関数宣言転送します:
//ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

#include <list>

class MyWindow;
	
std::list< MyWindow *> windows;

class MyWindow
{
public:

	HWND hWnd;



	MyWindow()
		:hWnd(NULL)
	{
		windows.push_back(this);
	}

	virtual ~MyWindow()
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			if (*it == this)
			{
				windows.erase(it);
				break;
			}
		}
	}

	static MyWindow * find(HWND key)
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			MyWindow *target = *it;

			if (target->hWnd == key)
			{
				return target;
			}

		}

		return NULL;
	}



	//
	//  関数: MyRegisterClass()
	//
	//  目的: ウィンドウ クラス登録します。
	//
	ATOM MyRegisterClass(HINSTANCE hInstance)
	{
		WNDCLASSEXW wcex;

		wcex.cbSize = sizeof(WNDCLASSEX);

		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = WndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInstance;
		wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT7));
		wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
		wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT7);
		wcex.lpszClassName = szWindowClass;
		wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

		return RegisterClassExW(&wcex);
	}

	//
	//   関数: InitInstance(HINSTANCE, int)
	//
	//   目的: インスタンス ハンドルを保存して、メイン ウィンドウ作成します。
	//
	//   コメント:
	//
	//        この関数で、グローバル変数インスタンス ハンドルを保存し、
	//        メイン プログラム ウィンドウ作成および表示します。
	//

	int blocks[100][100];

	BOOL InitInstance()
	{
		hInst = hInstance; // グローバル変数インスタンス処理を格納します。

		ATOM c = MyRegisterClass(hInstance);
		x = 0;
		y = 0;
		boxType = 0;

		hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

		for(int x = 0 ; x < 100 ; x++)
		{
			for (int y = 0; y < 100; y++)
			{
				blocks[y][x] = 0;
			}
		}

		if (!hWnd)
		{
			return FALSE;
		}

		return TRUE;
	}

	BOOL ShowWindow()
	{
		BOOL ret;
		ret = ::ShowWindow(hWnd, SW_SHOW);
		::UpdateWindow(hWnd);

		return ret;
	}


	HINSTANCE hInstance;
	MSG msg;
	BOOL run;
	int x;
	int y;
	BOOL Main()
	{

		HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT7));
		run = true;
		int rc;
		// メイン メッセージ ループ:
		while (run)
		{
			DWORD obj = MsgWaitForMultipleObjectsEx(0, NULL,  100 , QS_PAINT| QS_ALLEVENTS,0);
			if (obj <= WAIT_OBJECT_0)
			{
				while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				{
					if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
					{
						TranslateMessage(&msg);
						DispatchMessage(&msg);
					}
					if (msg.message == WM_QUIT) {
						run = FALSE;
					}
					if (msg.message == WM_CLOSE) {
						run = FALSE;
					}

				}
			}
			else if (obj == WAIT_TIMEOUT)
			{
				y++;
				PAINTSTRUCT ps;
				HDC hdc = BeginPaint(hWnd, &ps);
				this->OnPaint(ps);
				EndPaint(hWnd, &ps);
				::UpdateWindow(hWnd);
				RECT Rect2 = { 0,0,48*9,48 * 100 };
				InvalidateRect(hWnd, &Rect2, TRUE);
			}
			else if (obj == WAIT_FAILED)
			{
				rc = GetLastError();
			}
			else {

			}
		}


		return TRUE;

	}

	int boxType;

	BOOL WriteBoxOLDBox()
	{
		int width = 24;

		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 48));
		for (int y = 0; y < 30; y++)
		{
			for (int x = 0; x < 8; x++)
			{
				if (blocks[y][x] == 0)
				{
					continue;
				}

				RECT Rect = { 0,0,48,48 };
				BOOL ret;

				Rect.left = width * x + 1;
				Rect.right = width * (x + 1) - 1;
				Rect.top = width * y + 1;
				Rect.bottom = width * (y + 1) - 1;

				ret = FillRect(hdc, &Rect, hBrush);


			}
		}

		DeleteObject(hBrush);

		return FALSE;
	}


	BOOL WriteBox()
	{
		WriteBoxOLDBox();

		switch (boxType)
		{
		case 0:
			return WriteBoxI();
		case 1:
			return WriteBoxL();
		case 2:
			return WriteBoxZ();

		}

		return TRUE;
	}

	BOOL WriteBoxZ()
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 246));

		int width = 24;

		RECT Rect = { 0,0,48,48 };
		BOOL ret;

		Rect.left = width * x + 1;
		Rect.right = width * (x + 1) - 1;
		Rect.top = width * y + 1;
		Rect.bottom = width * (y + 1) - 1;

		ret = FillRect(hdc, &Rect, hBrush);


		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.left += width;
		Rect.right += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);


		DeleteObject(hBrush);

		return TRUE;
	}


	BOOL WriteBoxL()
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 246 , 48));

		int width = 24;

		RECT Rect = { 0,0,48,48 };
		BOOL ret;

		Rect.left = width * x + 1;
		Rect.right = width * (x + 1) -1 ;
		Rect.top = width * y + 1;
		Rect.bottom = width * (y + 1) -1;

		ret = FillRect(hdc, &Rect, hBrush);


		Rect.top    += width; 
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.left   += width;
		Rect.right  += width;
		ret = FillRect(hdc, &Rect, hBrush);

		DeleteObject(hBrush);

		return TRUE;
	}

	BOOL WriteBoxI()
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB( 246 , 48 , 48));

		int width = 24;

		RECT Rect = { 0,0,48,48 };
		BOOL ret;

		Rect.left = width * x + 1;
		Rect.right = width * (x + 1) - 1;
		Rect.top = width * y + 1;
		Rect.bottom = width * (y + 1) - 1;

		ret = FillRect(hdc, &Rect, hBrush);


		//Rect.left   += width;
		//Rect.right  += width;
		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		DeleteObject(hBrush);

		return TRUE;
	}

	BOOL SaveBoxI()
	{
		blocks[y  ][x] = 1;
		blocks[y+1][x] = 1;
		blocks[y+2][x] = 1;
		blocks[y+3][x] = 1;
		return TRUE;
	}


	BOOL OnPaint(PAINTSTRUCT &ps)
	{
		if (x > 8) {
			x = 0;
		}
		if (x <0) {
			x = 8;
		}
		if (y > 20) {
			switch (boxType)
			{
			case 0:
				SaveBoxI();
				break;
			case 1:
				break;
			case 2:
				break;
			}

			y = 0;
			boxType++;
			if (boxType > 2)
			{
				boxType = 0;
			}
		}

		this->WriteBox();

		return TRUE;
	}



	BOOL OnKey(WPARAM wParam)
	{
		if (wParam == VK_LEFT)
		{
			x++;
		}
		if (wParam == VK_RIGHT)
		{
			x--;
		}
		return TRUE;
	}


};


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: ここにコードを挿入してください。

    // グローバル文字列初期化しています。
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT7, szWindowClass, MAX_LOADSTRING);
    //MyRegisterClass(hInstance);



	MyWindow win;



	win.hInstance = hInstance;

	// アプリケーション初期化を実行します:
	if (!win.InitInstance())
	{
		return FALSE;
	}

	BOOL ret;

	win.ShowWindow();

	ret = win.Main();

	if (ret)
	{
		return 0;
	}else {
		return (int)win.msg.wParam;
	}



}






//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    メイン ウィンドウメッセージを処理します。
//
//  WM_COMMAND  - アプリケーション メニューの処理
//  WM_PAINT    - メイン ウィンドウの描画
//  WM_DESTROY  - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 選択されたメニューの解析:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
		break;
	case WM_KEYDOWN:
		{
			MyWindow *target = MyWindow::find(hWnd);
			target->OnKey(wParam);
		}
	break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

			MyWindow *target = MyWindow::find(hWnd);
			target->OnPaint(ps);


            // TODO: HDC を使用する描画コードをここに追加してください...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// バージョン情報ボックスメッセージ ハンドラーです。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

anond:20190103170543

テトリス

落ちてくるブロックの描き方

わかりやす関数化してみた

まずはブロックの種類は3種類

 

WriteBoxLとWriteBoxIとWriteBoxZ

の違いをよく見比べて

自力で違いがわかれば

プログラマーにはなれるとおもう

とはいえ、コレを自力でわかるならもっと儲かる仕事あるとはおもうけどな

 

	BOOL WriteBox()
	{
		switch (boxType)
		{
		case 0:
			return WriteBoxI();
		case 1:
			return WriteBoxL();
		case 2:
			return WriteBoxZ();

		}
	}
// WindowsProject7.cpp: アプリケーションエントリ ポイント定義します。
//

#include "stdafx.h"
#include "WindowsProject7.h"

#define MAX_LOADSTRING 100

// グローバル変数:
HINSTANCE hInst;                                // 現在インターフェイス
WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーテキスト
WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名

// このコード モジュールに含まれ関数宣言転送します:
//ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

#include <list>

class MyWindow;
	
std::list< MyWindow *> windows;

class MyWindow
{
public:

	HWND hWnd;



	MyWindow()
		:hWnd(NULL)
	{
		windows.push_back(this);
	}

	virtual ~MyWindow()
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			if (*it == this)
			{
				windows.erase(it);
				break;
			}
		}
	}

	static MyWindow * find(HWND key)
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			MyWindow *target = *it;

			if (target->hWnd == key)
			{
				return target;
			}

		}

		return NULL;
	}



	//
	//  関数: MyRegisterClass()
	//
	//  目的: ウィンドウ クラス登録します。
	//
	ATOM MyRegisterClass(HINSTANCE hInstance)
	{
		WNDCLASSEXW wcex;

		wcex.cbSize = sizeof(WNDCLASSEX);

		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = WndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInstance;
		wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT7));
		wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
		wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT7);
		wcex.lpszClassName = szWindowClass;
		wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

		return RegisterClassExW(&wcex);
	}

	//
	//   関数: InitInstance(HINSTANCE, int)
	//
	//   目的: インスタンス ハンドルを保存して、メイン ウィンドウ作成します。
	//
	//   コメント:
	//
	//        この関数で、グローバル変数インスタンス ハンドルを保存し、
	//        メイン プログラム ウィンドウ作成および表示します。
	//
	BOOL InitInstance()
	{
		hInst = hInstance; // グローバル変数インスタンス処理を格納します。

		ATOM c = MyRegisterClass(hInstance);
		x = 0;
		y = 0;
		boxType = 0;

		hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

		if (!hWnd)
		{
			return FALSE;
		}

		return TRUE;
	}

	BOOL ShowWindow()
	{
		BOOL ret;
		ret = ::ShowWindow(hWnd, SW_SHOW);
		::UpdateWindow(hWnd);

		return ret;
	}


	HINSTANCE hInstance;
	MSG msg;
	BOOL run;
	int x;
	int y;
	BOOL Main()
	{

		HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT7));
		run = true;
		int rc;
		// メイン メッセージ ループ:
		while (run)
		{
			DWORD obj = MsgWaitForMultipleObjectsEx(0, NULL,  100 , QS_PAINT| QS_ALLEVENTS,0);
			if (obj <= WAIT_OBJECT_0)
			{
				while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				{
					if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
					{
						TranslateMessage(&msg);
						DispatchMessage(&msg);
					}
					if (msg.message == WM_QUIT) {
						run = FALSE;
					}
					if (msg.message == WM_CLOSE) {
						run = FALSE;
					}

				}
			}
			else if (obj == WAIT_TIMEOUT)
			{
				y++;
				PAINTSTRUCT ps;
				HDC hdc = BeginPaint(hWnd, &ps);
				this->OnPaint(ps);
				EndPaint(hWnd, &ps);
				::UpdateWindow(hWnd);
				RECT Rect2 = { 0,0,48*9,48 * 8 };
				InvalidateRect(hWnd, &Rect2, TRUE);
			}
			else if (obj == WAIT_FAILED)
			{
				rc = GetLastError();
			}
			else {

			}
		}


		return TRUE;

	}

	int boxType;

	BOOL WriteBox()
	{
		switch (boxType)
		{
		case 0:
			return WriteBoxI();
		case 1:
			return WriteBoxL();
		case 2:
			return WriteBoxZ();

		}
	}

	BOOL WriteBoxZ()
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 246));

		int width = 24;

		RECT Rect = { 0,0,48,48 };
		BOOL ret;

		Rect.left = width * x + 1;
		Rect.right = width * (x + 1) - 1;
		Rect.top = width * y + 1;
		Rect.bottom = width * (y + 1) - 1;

		ret = FillRect(hdc, &Rect, hBrush);


		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.left += width;
		Rect.right += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);


		DeleteObject(hBrush);

		return TRUE;
	}


	BOOL WriteBoxL()
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 246));

		int width = 24;

		RECT Rect = { 0,0,48,48 };
		BOOL ret;

		Rect.left = width * x + 1;
		Rect.right = width * (x + 1) -1 ;
		Rect.top = width * y + 1;
		Rect.bottom = width * (y + 1) -1;

		ret = FillRect(hdc, &Rect, hBrush);


		Rect.top    += width; 
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.left   += width;
		Rect.right  += width;
		ret = FillRect(hdc, &Rect, hBrush);

		DeleteObject(hBrush);

		return TRUE;
	}

	BOOL WriteBoxI()
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 246));

		int width = 24;

		RECT Rect = { 0,0,48,48 };
		BOOL ret;

		Rect.left = width * x + 1;
		Rect.right = width * (x + 1) - 1;
		Rect.top = width * y + 1;
		Rect.bottom = width * (y + 1) - 1;

		ret = FillRect(hdc, &Rect, hBrush);


		//Rect.left   += width;
		//Rect.right  += width;
		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		Rect.top += width;
		Rect.bottom += width;
		ret = FillRect(hdc, &Rect, hBrush);

		DeleteObject(hBrush);

		return TRUE;
	}


	BOOL OnPaint(PAINTSTRUCT &ps)
	{
		if (x > 8) {
			x = 0;
		}
		if (x <0) {
			x = 8;
		}
		if (y > 8) {
			y = 0;
			boxType++;
			if (boxType > 2)
			{
				boxType = 0;
			}
		}

		this->WriteBox();

		return TRUE;
	}



	BOOL OnKey()
	{
		x++;
		return TRUE;
	}


};


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: ここにコードを挿入してください。

    // グローバル文字列初期化しています。
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT7, szWindowClass, MAX_LOADSTRING);
    //MyRegisterClass(hInstance);



	MyWindow win;



	win.hInstance = hInstance;

	// アプリケーション初期化を実行します:
	if (!win.InitInstance())
	{
		return FALSE;
	}

	BOOL ret;

	win.ShowWindow();

	ret = win.Main();

	if (ret)
	{
		return 0;
	}else {
		return (int)win.msg.wParam;
	}



}






//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    メイン ウィンドウメッセージを処理します。
//
//  WM_COMMAND  - アプリケーション メニューの処理
//  WM_PAINT    - メイン ウィンドウの描画
//  WM_DESTROY  - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 選択されたメニューの解析:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
		break;
	case WM_KEYDOWN:
		{
			MyWindow *target = MyWindow::find(hWnd);
			target->OnKey();
		}
	break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

			MyWindow *target = MyWindow::find(hWnd);
			target->OnPaint(ps);


            // TODO: HDC を使用する描画コードをここに追加してください...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// バージョン情報ボックスメッセージ ハンドラーです。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

anond:20190101175055

テトリス風?プログラムに向けて

第何回だろうな

キー入力を追加した

まだ、何を押してもブロックが右に移動するだけ(右端にいくと左にワープ

タイマー自動落下

 

でもまぁ ここまでサンプルがあるとほぼテトリスは見えてきた

// WindowsProject7.cpp: アプリケーションエントリ ポイント定義します。
//

#include "stdafx.h"
#include "WindowsProject7.h"

#define MAX_LOADSTRING 100

// グローバル変数:
HINSTANCE hInst;                                // 現在インターフェイス
WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーテキスト
WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名

// このコード モジュールに含まれ関数宣言転送します:
//ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

#include <list>

class MyWindow;
	
std::list< MyWindow *> windows;

class MyWindow
{
public:

	HWND hWnd;



	MyWindow()
		:hWnd(NULL)
	{
		windows.push_back(this);
	}

	virtual ~MyWindow()
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			if (*it == this)
			{
				windows.erase(it);
				break;
			}
		}
	}

	static MyWindow * find(HWND key)
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			MyWindow *target = *it;

			if (target->hWnd == key)
			{
				return target;
			}

		}

		return NULL;
	}



	//
	//  関数: MyRegisterClass()
	//
	//  目的: ウィンドウ クラス登録します。
	//
	ATOM MyRegisterClass(HINSTANCE hInstance)
	{
		WNDCLASSEXW wcex;

		wcex.cbSize = sizeof(WNDCLASSEX);

		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = WndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInstance;
		wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT7));
		wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
		wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT7);
		wcex.lpszClassName = szWindowClass;
		wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

		return RegisterClassExW(&wcex);
	}

	//
	//   関数: InitInstance(HINSTANCE, int)
	//
	//   目的: インスタンス ハンドルを保存して、メイン ウィンドウ作成します。
	//
	//   コメント:
	//
	//        この関数で、グローバル変数インスタンス ハンドルを保存し、
	//        メイン プログラム ウィンドウ作成および表示します。
	//
	BOOL InitInstance()
	{
		hInst = hInstance; // グローバル変数インスタンス処理を格納します。

		ATOM c = MyRegisterClass(hInstance);
		x = 0;
		y = 0;

		hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

		if (!hWnd)
		{
			return FALSE;
		}

		return TRUE;
	}

	BOOL ShowWindow()
	{
		BOOL ret;
		ret = ::ShowWindow(hWnd, SW_SHOW);
		::UpdateWindow(hWnd);

		return ret;
	}


	HINSTANCE hInstance;
	MSG msg;
	BOOL run;
	int x;
	int y;
	BOOL Main()
	{

		HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT7));
		run = true;
		int rc;
		// メイン メッセージ ループ:
		while (run)
		{
			DWORD obj = MsgWaitForMultipleObjectsEx(0, NULL,  100 , QS_PAINT| QS_ALLEVENTS,0);
			if (obj <= WAIT_OBJECT_0)
			{
				while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				{
					if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
					{
						TranslateMessage(&msg);
						DispatchMessage(&msg);
					}
					if (msg.message == WM_QUIT) {
						run = FALSE;
					}
					if (msg.message == WM_CLOSE) {
						run = FALSE;
					}

				}
			}
			else if (obj == WAIT_TIMEOUT)
			{
				y++;
				PAINTSTRUCT ps;
				HDC hdc = BeginPaint(hWnd, &ps);
				this->OnPaint(ps);
				EndPaint(hWnd, &ps);
				::UpdateWindow(hWnd);
				RECT Rect2 = { 0,0,48*9,48 * 8 };
				InvalidateRect(hWnd, &Rect2, TRUE);
			}
			else if (obj == WAIT_FAILED)
			{
				rc = GetLastError();
			}
			else {

			}
		}


		return TRUE;

	}

	BOOL OnPaint(PAINTSTRUCT &ps)
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 246));
		RECT Rect = { 0,0,48,48 };
		Rect.left = 48 * x;
		Rect.right = 48 * (x+1);
		Rect.top = 48 * y;
		Rect.bottom = 48 * (y+1);
		if (x > 8) {
			x = 0;
		}
		if (x <0) {
			x = 8;
		}
		if (y > 8) {
			y = 0;
		}
		BOOL ret = FillRect(ps.hdc, &Rect, hBrush);
		DeleteObject(hBrush);

		return TRUE;
	}

	BOOL OnKey()
	{
		x++;
		return TRUE;
	}


};


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: ここにコードを挿入してください。

    // グローバル文字列初期化しています。
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT7, szWindowClass, MAX_LOADSTRING);
    //MyRegisterClass(hInstance);



	MyWindow win;



	win.hInstance = hInstance;

	// アプリケーション初期化を実行します:
	if (!win.InitInstance())
	{
		return FALSE;
	}

	BOOL ret;

	win.ShowWindow();

	ret = win.Main();

	if (ret)
	{
		return 0;
	}else {
		return (int)win.msg.wParam;
	}



}






//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    メイン ウィンドウメッセージを処理します。
//
//  WM_COMMAND  - アプリケーション メニューの処理
//  WM_PAINT    - メイン ウィンドウの描画
//  WM_DESTROY  - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 選択されたメニューの解析:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
		break;
	case WM_KEYDOWN:
		{
			MyWindow *target = MyWindow::find(hWnd);
			target->OnKey();
		}
	break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

			MyWindow *target = MyWindow::find(hWnd);
			target->OnPaint(ps);


            // TODO: HDC を使用する描画コードをここに追加してください...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// バージョン情報ボックスメッセージ ハンドラーです。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

2019-01-01

anond:20190101172100

タイマーを使ったアニメーションを付けた

// WindowsProject7.cpp: アプリケーションエントリ ポイント定義します。
//

#include "stdafx.h"
#include "WindowsProject7.h"

#define MAX_LOADSTRING 100

// グローバル変数:
HINSTANCE hInst;                                // 現在インターフェイス
WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーテキスト
WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名

// このコード モジュールに含まれ関数宣言転送します:
//ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

#include <list>

class MyWindow;
	
std::list< MyWindow *> windows;

class MyWindow
{
public:

	HWND hWnd;



	MyWindow()
		:hWnd(NULL)
	{
		windows.push_back(this);
	}

	virtual ~MyWindow()
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			if (*it == this)
			{
				windows.erase(it);
				break;
			}
		}
	}

	static MyWindow * find(HWND key)
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			MyWindow *target = *it;

			if (target->hWnd == key)
			{
				return target;
			}

		}

		return NULL;
	}



	//
	//  関数: MyRegisterClass()
	//
	//  目的: ウィンドウ クラス登録します。
	//
	ATOM MyRegisterClass(HINSTANCE hInstance)
	{
		WNDCLASSEXW wcex;

		wcex.cbSize = sizeof(WNDCLASSEX);

		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = WndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInstance;
		wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT7));
		wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
		wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT7);
		wcex.lpszClassName = szWindowClass;
		wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

		return RegisterClassExW(&wcex);
	}

	//
	//   関数: InitInstance(HINSTANCE, int)
	//
	//   目的: インスタンス ハンドルを保存して、メイン ウィンドウ作成します。
	//
	//   コメント:
	//
	//        この関数で、グローバル変数インスタンス ハンドルを保存し、
	//        メイン プログラム ウィンドウ作成および表示します。
	//
	BOOL InitInstance()
	{
		hInst = hInstance; // グローバル変数インスタンス処理を格納します。

		ATOM c = MyRegisterClass(hInstance);
		y = 0;

		hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

		if (!hWnd)
		{
			return FALSE;
		}

		return TRUE;
	}

	BOOL ShowWindow()
	{
		BOOL ret;
		ret = ::ShowWindow(hWnd, SW_SHOW);
		::UpdateWindow(hWnd);

		return ret;
	}


	HINSTANCE hInstance;
	MSG msg;
	BOOL run;
	int y;
	BOOL Main()
	{

		HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT7));
		run = true;
		int rc;
		// メイン メッセージ ループ:
		while (run)
		{
			DWORD obj = MsgWaitForMultipleObjectsEx(0, NULL,  100 , QS_PAINT| QS_ALLEVENTS,0);
			if (obj <= WAIT_OBJECT_0)
			{
				while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				{
					if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
					{
						TranslateMessage(&msg);
						DispatchMessage(&msg);
					}
					if (msg.message == WM_QUIT) {
						run = FALSE;
					}
					if (msg.message == WM_CLOSE) {
						run = FALSE;
					}

				}
			}
			else if (obj == WAIT_TIMEOUT)
			{
				y++;
				PAINTSTRUCT ps;
				HDC hdc = BeginPaint(hWnd, &ps);
				this->OnPaint(ps);
				EndPaint(hWnd, &ps);
				::UpdateWindow(hWnd);
				RECT Rect2 = { 0,0,48,48 * 8 };
				InvalidateRect(hWnd, &Rect2, TRUE);
			}
			else if (obj == WAIT_FAILED)
			{
				rc = GetLastError();
			}
			else {

			}
		}


		return TRUE;

	}

	BOOL OnPaint(PAINTSTRUCT &ps)
	{
		HDC hdc = GetDC(hWnd);
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 246));
		RECT Rect = { 0,0,48,48 };
		Rect.top = 48 * y;
		Rect.bottom = 48 * (y+1);
		if (y > 8) {
			y = 0;
		}
		BOOL ret = FillRect(ps.hdc, &Rect, hBrush);
		DeleteObject(hBrush);

		return TRUE;
	}


};


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: ここにコードを挿入してください。

    // グローバル文字列初期化しています。
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT7, szWindowClass, MAX_LOADSTRING);
    //MyRegisterClass(hInstance);



	MyWindow win;



	win.hInstance = hInstance;

	// アプリケーション初期化を実行します:
	if (!win.InitInstance())
	{
		return FALSE;
	}

	BOOL ret;

	win.ShowWindow();

	ret = win.Main();

	if (ret)
	{
		return 0;
	}else {
		return (int)win.msg.wParam;
	}



}






//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    メイン ウィンドウメッセージを処理します。
//
//  WM_COMMAND  - アプリケーション メニューの処理
//  WM_PAINT    - メイン ウィンドウの描画
//  WM_DESTROY  - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 選択されたメニューの解析:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

			MyWindow *target = MyWindow::find(hWnd);
			target->OnPaint(ps);


            // TODO: HDC を使用する描画コードをここに追加してください...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// バージョン情報ボックスメッセージ ハンドラーです。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

anond:20190101162210

やすいように フルソー

青い■を表示するだけ

// WindowsProject7.cpp: アプリケーションエントリ ポイント定義します。
//

#include "stdafx.h"
#include "WindowsProject7.h"

#define MAX_LOADSTRING 100

// グローバル変数:
HINSTANCE hInst;                                // 現在インターフェイス
WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーテキスト
WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名

// このコード モジュールに含まれ関数宣言転送します:
//ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

#include <list>

class MyWindow;
	
std::list< MyWindow *> windows;

class MyWindow
{
public:

	HWND hWnd;



	MyWindow()
		:hWnd(NULL)
	{
		windows.push_back(this);
	}

	virtual ~MyWindow()
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			if (*it == this)
			{
				windows.erase(it);
				break;
			}
		}
	}

	static MyWindow * find(HWND key)
	{
		std::list< MyWindow *>::iterator it;
		for (it = windows.begin(); it != windows.end(); it++)
		{
			MyWindow *target = *it;

			if (target->hWnd == key)
			{
				return target;
			}

		}

		return NULL;
	}



	//
	//  関数: MyRegisterClass()
	//
	//  目的: ウィンドウ クラス登録します。
	//
	ATOM MyRegisterClass(HINSTANCE hInstance)
	{
		WNDCLASSEXW wcex;

		wcex.cbSize = sizeof(WNDCLASSEX);

		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = WndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInstance;
		wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT7));
		wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
		wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT7);
		wcex.lpszClassName = szWindowClass;
		wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

		return RegisterClassExW(&wcex);
	}

	//
	//   関数: InitInstance(HINSTANCE, int)
	//
	//   目的: インスタンス ハンドルを保存して、メイン ウィンドウ作成します。
	//
	//   コメント:
	//
	//        この関数で、グローバル変数インスタンス ハンドルを保存し、
	//        メイン プログラム ウィンドウ作成および表示します。
	//
	BOOL InitInstance()
	{
		hInst = hInstance; // グローバル変数インスタンス処理を格納します。

		ATOM c = MyRegisterClass(hInstance);


		hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

		if (!hWnd)
		{
			return FALSE;
		}

		return TRUE;
	}

	BOOL ShowWindow()
	{
		BOOL ret;
		ret = ::ShowWindow(hWnd, SW_SHOW);
		::UpdateWindow(hWnd);

		return ret;
	}


	HINSTANCE hInstance;
	MSG msg;

	BOOL Main()
	{

		HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT7));

		// メイン メッセージ ループ:
		while (GetMessage(&msg, nullptr, 0, 0))
		{
			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}


		return TRUE;

	}

	BOOL OnPaint(PAINTSTRUCT &ps)
	{
		HBRUSH hBrush = CreateSolidBrush(RGB(48, 48, 246));
		RECT Rect = { 0,0,48,48 };
		BOOL ret = FillRect(ps.hdc, &Rect, hBrush);
		DeleteObject(hBrush);

		return TRUE;
	}


};


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: ここにコードを挿入してください。

    // グローバル文字列初期化しています。
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT7, szWindowClass, MAX_LOADSTRING);
    //MyRegisterClass(hInstance);



	MyWindow win;



	win.hInstance = hInstance;

	// アプリケーション初期化を実行します:
	if (!win.InitInstance())
	{
		return FALSE;
	}

	BOOL ret;

	win.ShowWindow();

	ret = win.Main();

	if (ret)
	{
		return 0;
	}else {
		return (int)win.msg.wParam;
	}



}






//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    メイン ウィンドウメッセージを処理します。
//
//  WM_COMMAND  - アプリケーション メニューの処理
//  WM_PAINT    - メイン ウィンドウの描画
//  WM_DESTROY  - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 選択されたメニューの解析:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

			MyWindow *target = MyWindow::find(hWnd);
			target->OnPaint(ps);


            // TODO: HDC を使用する描画コードをここに追加してください...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// バージョン情報ボックスメッセージ ハンドラーです。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

ログイン ユーザー登録
ようこそ ゲスト さん