[C++]『ゲームプログラミングC++』Chapter05 : Intel Macへの移植

[Intel Mac, Big Sur 11.6.5, clang 12.0.0, no IDE]

前回の続きです。

検討中のコードをM1 MacからIntel Macへ移植しました。移植と言ってもソースコードはそのまま、Makefileの方はINCLUDEとLIBRARYを書き直しです。

その結果、UNSUPPORTEDの表示は消えましたが、Windowは白いままです。

# コンパイラ設定
COMPILER = clang++
DEBUG = -g

# フラグ設定
CPPFLAGS = $(shell pkg-config sdl2 --cflags --libs) -std=c++11
LDFLAGS = -lc++ -framework CoreFoundation -framework OpenGL

# includeパス(-I)
INCLUDE = -I./include/act -I./include/base -I./include/compo -I./include/etc \
-I/usr/local/Cellar/sdl2/2.0.22/include -I/usr/local/Cellar/sdl2_image/2.0.5/include \
-I/usr/local/Cellar/glew/2.2.0_1/include -I/usr/local/include/freetype2/freetype \
-I/usr/local/include/SOIL -I/usr/local/include -I/Volumes/DATA/code/cpp/mylib/include

# ライブラリ直接パス(-l)
LIBRARY_l = -lsdl2 -lsdl2_image -lglew -lsdl2_mixer \
/mylib/lib/split.dylib

# ライブラリパス(-L)
LIBRARY_L = -L/usr/local/Cellar/sdl2/2.0.22/lib -L/usr/local/Cellar/sdl2_image/2.0.5/lib \
-L/usr/local/Cellar/glew/2.2.0_1/lib -L/usr/local/lib

# 実行ファイル設定
TARGET = Game
TARGETDIR = ./bin

# ソースコードパス
SRCROOT = ./src

# oファイルの出力ディレクトリ
OBJROOT = ./obj

# プロジェクト
PROJ = Chapter05_04

# ソースディレクトリのリスト化
SRCDIRS := $(shell find $(SRCROOT) -type d)

# ソースディレクトリから全てのcppファイルをリスト化
SRCS   = $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.cpp))

# cppファイルのリストからオブジェクトファイルをリスト化
OBJS   = $(addprefix $(OBJROOT), $(patsubst ./src%,%,$(SRCS:.cpp=.o)))

# oファイルの出力ディレクトリをリスト化
OBJDIRS   = $(addprefix $(OBJROOT), $(patsubst ./%,/%,$(SRCDIRS)))

# cppファイルからoファイル作成
$(OBJROOT)/%.o: $(SRCROOT)/%.cpp
	@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
	$(COMPILER) $(CPPFLAGS) $(INCLUDE) $(DEBUG) -o $@ -c $<

# oファイルから実行ファイル作成
$(TARGET):$(OBJS)
	$(COMPILER) -o $(TARGETDIR)/$@ $(OBJS) $(LIBRARY_l) $(LIBRARY_L) $(LDFLAGS)

# 全ソース・コンパイル&ビルド
.PHONY:all
all: clean $(OBJS) $(TARGET)

# oファイル・実行ファイル削除
.PHONY:clean
clean:
	rm -rf $(OBJS) $(TARGETDIR)/$(TARGET)

[C++]『ゲームプログラミングC++』Chapter05 : main関数修正

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, no IDE]

4/12の詰み報告から一歩前進しました。作業ディレクトリをhomeから実行ファイルのあるディレクトリに変更してShadersディレクトリにアクセスできるようにしました。

しかし起動はするものの画面は真っ白です。調べたところM1環境に問題があるようなので、Intel Macにて検討を継続します。

やはりこの本は初級者には手ごわすぎます。C++を一通り使いこなせる中級かつゲーム製作経験者がターゲットだと思います。

#include "Game.h"
#include "split.h" // 自製ライブラリ

split spt;
char tmp[256];

int main(int argc, char** argv)
{
	// 変更前の作業ディレクトリ確認
    getcwd(tmp, 256);
    cout << "変更前cwd: " << tmp << endl;

	// 作業ディレクトリ変更(実行ファイルのディレクトリ)
	int rtn = spt.chCWD(argv[0], '/', 0, -2);
    cout << rtn << endl ;

	// 変更後の作業ディレクトリ確認
    getcwd(tmp, 256);
    cout << "変更後cwd: " << tmp << endl;

	Game game;
	bool success = game.Initialize();
	if (success)
	{
		game.RunLoop();
	}
	game.Shutdown();
	return 0;
}
変更前cwd: /Users/[ユーザID]
0
変更後cwd: /Volumes/DATA_m1/code/cpp/gameprogcpp/Chapter05_04/bin
UNSUPPORTED (log once): POSSIBLE ISSUE: unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable

[C++]『ゲームプログラミングC++』Chapter03 ディレクトリ構成変更

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, no IDE]

cppファイルが13個フラットに並んでいると扱いにくいので、サブディレクトリに振り分けました。それに合わせてMakefileも書き換えました。

cppファイル関係図
# コンパイラ設定
COMPILER = clang++
DEBUG = -g

# フラグ設定
CPPFLAGS = $(shell pkg-config sdl2 --cflags --libs) -std=c++11
LDFLAGS = -lc++

# includeパス(-I)
INCLUDE = -I./include/act -I./include/base -I./include/compo -I/opt/homebrew/Cellar/sdl2/2.0.22/include \
-I/opt/homebrew/Cellar/sdl2_image/2.0.5/include -I/opt/homebrew/Cellar/glew/2.2.0_1/include \
-I/opt/homebrew/Cellar/sdl2_mixer/2.0.4_3/include -I/opt/homebrew/Cellar/sdl2_ttf/2.0.18_1/include -I/usr/local/include

# ライブラリ直接パス(-l)
LIBRARY_l = -lsdl2 -lsdl2_image -lglew  -lsdl2_mixer -lsdl2_ttf

# ライブラリパス(-L)
LIBRARY_L = -L/opt/homebrew/Cellar/sdl2/2.0.22/lib -L/opt/homebrew/Cellar/sdl2_image/2.0.5/lib \
-L/opt/homebrew/Cellar/glew/2.2.0_1/lib -L/opt/homebrew/Cellar/sdl2_mixer/2.0.4_3/lib \
-L/opt/homebrew/Cellar/sdl2_ttf/2.0.18_1/lib -L/usr/local/lib

# 実行ファイル設定
TARGET = Game
TARGETDIR = ./bin

# ソースコードパス
SRCROOT   = ./src

# oファイルの出力ディレクトリ
OBJROOT   = ./obj

# ソースディレクトリのリスト化
SRCDIRS := $(shell find $(SRCROOT) -type d)

# ソースディレクトリから全てのcppファイルをリスト化
SRCS   = $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.cpp))

# cppファイルのリストからオブジェクトファイルをリスト化
OBJS   = $(addprefix $(OBJROOT), $(patsubst ./src%,%,$(SRCS:.cpp=.o)))

# oファイルの出力ディレクトリをリスト化
OBJDIRS   = $(addprefix $(OBJROOT), $(patsubst ./%,/%,$(SRCDIRS)))

# cppファイルからoファイル作成
$(OBJROOT)/%.o: $(SRCROOT)/%.cpp
	@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
	$(COMPILER) $(CPPFLAGS) $(INCLUDE) $(DEBUG) -o $@ -c $<

# oファイルから実行ファイル作成
$(TARGET):$(OBJS)
	$(COMPILER) -o $(TARGETDIR)/$@ $(OBJS) $(LIBRARY_l) $(LIBRARY_L) $(LDFLAGS) 

# コンパイル&ビルド
.PHONY:all
all: clean $(TARGET)

# oファイル・実行ファイル削除
.PHONY:clean
clean:
	rm -rf $(OBJS) $(TARGETDIR)/$(TARGET)

[C++]『ゲームプログラミングC++』Chapter03 学習再開

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, no IDE]

この本に関しては4/14以来の記事になります。2ヶ月ぶりに戻ってきました。

Chapter05で詰んでしまい学習を中断したのですが、あれからCMakeを習得するなどそれなりにスキルアップしたので再挑戦します。当時、調子に乗って買ってしまった”スタンフォード物理学再入門 力学”を少しは使おうという意図もあります。Chapter03から復習していきます。

後から見返すとそのプロジェクトを何のために作ったのか分からなくて少々困りました。テキストファイル名などに最低限の説明を残しておくべきですね。まだディレクトリ構成が定まっていないため、Gitは使っていません。

とりあえずライブラリの整理などビルドできる環境を再構築して、ゲームを作成し動かしてみました。

[C++] ”プログラミング入門” : GUIソースコード修正 Makefile, CMakeLists.txt

[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]

プロジェクトのディレクトリ構成は下図の通りです。

Makefile, CMakeLists.txtも載せておきます。

# コンパイラ
COMPILER = clang++
DEBUG = -g

# オプション
CPPFLAGS = $(shell fltk-config --use-gl --use-images --cxxflags ) -std=c++11 
LDFLAGS = $(shell fltk-config --use-gl --use-images --ldflags ) -lc++

# includeパス(-I)
INCLUDE = -I./include -I/opt/homebrew/Cellar/libpng/1.6.37/include -I/opt/homebrew/Cellar/fltk/1.3.8/include \
-I/opt/homebrew/Cellar/opencv/4.5.5_2/include

# ライブラリ直接パス(-l)
LIBRARYD = -lpng16 -lz -lopencv_core -lopencv_imgcodecs -lopencv_highgui -lopencv_imgproc

# ライブラリパス(-L)
LIBRARY = -L/opt/homebrew/Cellar/jpeg/9e/lib -L/opt/homebrew/Cellar/libpng/1.6.37/lib \
-L/usr/local/lib -L/opt/homebrew/Cellar/opencv/4.5.5_2/lib

# ソースファイル
SRCDIR = ./src
SRCS = $(shell find $(SRCDIR) -type f)

# オブジェクトファイル
OBJDIR = ./obj
OBJS   = $(addprefix $(OBJDIR), $(patsubst ./src%,%,$(SRCS:.cpp=.o)))

# 実行ファイル
TARGETDIR = ./bin
TARGET = PPPGui

# プロジェクト
PROJ = PPP02

# コンパイル
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
	$(COMPILER) $(CPPFLAGS) $(INCLUDE) $(DEBUG) -o $@ -c $<

# appファイル作成関連
POSTBUILD  = fltk-config --post

# ビルド:oファイルから実行ファイルとappファイル作成
$(TARGET):$(OBJS)
	$(COMPILER) -o $(TARGETDIR)/$@ $(OBJS) $(LIBRARYD) $(LDFLAGS) $(LIBRARY)
	cp $(TARGETDIR)/$(TARGET) ./app/$(TARGET)
	cd ./app && $(POSTBUILD) $(TARGET)
	mkdir ./app/$(TARGET).app/Contents/Resources
	cp ./images/$(TARGET).icns ./app/$(TARGET).app/Contents/Resources
	plutil -insert 'CFBundleIconFile' -string $(TARGET).icns ./app/$(TARGET).app/Contents/Info.plist
	rm -f ./app/$(TARGET)

# ファイル削除
.PHONY:clean
clean:
	rm -rf $(OBJS) $(TARGETDIR)/$(TARGET) $(TARGET).app $(SRCDIR)/.DS_Store ./app/*

# CMakeからappファイル作成
.PHONY : all
all:
	rm -rf build/* $(SRCDIR)/.DS_Store
	cd /Volumes/DATA_m1/code/cpp/projects/$(PROJ)/build && cmake .. && make
	mkdir ./build/$(TARGET).app/Contents/Resources
	cp ./images/$(TARGET).icns ./build/$(TARGET).app/Contents/Resources
	plutil -replace 'CFBundleIconFile' -string "$(TARGET).icns" ./build/$(TARGET).app/Contents/Info.plist

# 自製Makefileから実行ファイルおよびappファイル作成
.PHONY:all2
all2: clean $(TARGET)

# 実行ファイルからappファイル作成(Info.plistが必要)
.PHONY : exetoapp
exetoapp:
	mkdir $(TARGETDIR)/$(TARGET)
	mkdir $(TARGETDIR)/$(TARGET)/Contents
	mkdir $(TARGETDIR)/$(TARGET)/Contents/MacOS
	mkdir $(TARGETDIR)/$(TARGET)/Contents/Resources
	cp $(TARGETDIR)/$(TARGET).exe $(TARGETDIR)/$(TARGET)/Contents/MacOS
	cp ./Info.plist $(TARGETDIR)/$(TARGET)/Contents
	cp ./images/test.icns $(TARGETDIR)/$(TARGET)/Contents/Resources
	plutil -replace 'CFBundleIconFile' -string "test.icns" $(TARGETDIR)/$(TARGET)/Contents/Info.plist
cmake_minimum_required(VERSION 3.1)

# Project
Project(PPPGui VERSION 1.0.0)
FIND_PACKAGE(FLTK REQUIRED)
FIND_PACKAGE(OpenGL REQUIRED)
find_library(COCOA Cocoa)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_VERBOSE_MAKEFILE ON)

# Info.plist
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "")
set(MACOSX_BUNDLE_INFO_STRING "")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "")

# ファイル設定
file(GLOB SOURCE ./src/*.cpp ./include/*.h)

add_executable(${PROJECT_NAME}
    MACOSX_BUNDLE
    ${SOURCE}
    )

set(INCDIR ./include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/libpng/1.6.37/include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/fltk/1.3.8/include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/jpeg/9e/include)
include_directories(${INCDIR})

set(LIBS dl)
set(LIBS ${LIBS} z pthread c++)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_forms.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_gl.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_images.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/jpeg/9e/lib/libjpeg.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/libpng/1.6.37/lib/libpng.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk.dylib)

set(LIBDIR /opt/homebrew/Cellar/jpeg/9e/lib)
set(LIBDIR ${LIBDIR} /opt/homebrew/Cellar/libpng/1.6.37/lib)
set(LIBDIR ${LIBDIR} /opt/homebrew/Cellar/fltk/1.3.8/lib)
link_directories(${LIBDIR})

target_link_libraries(${PROJECT_NAME}
    ${FLTK}
    ${OpenGL}
    ${LIBS}
    ${COCOA})

[C++] ”プログラミング入門” : GUIソースコード修正 Gui.h, Gui.cpp他

[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]

Guiファイルについてはincludeのところを修正しました。

std_lib_facilities.hはストラウストラップ氏のホームページに公開しています。

#ifndef GUI_GUARD
#define GUI_GUARD

#include "Point.h"
#include <FL/Fl_Widget.H>
#include "Window.h"

namespace Graph_lib {
	
typedef void* Address;
typedef void (*Callback)(Address,Address);

template<class W> W& reference_to(Address pw)
{
	return *static_cast<W*>(pw);
}


class Widget {
public:
	Widget(Point xy, int w, int h, const string& s, Callback cb)
		:loc(xy), width(w), height(h), label(s), do_it(cb)
	{ }

	virtual void move(int dx,int dy) { hide(); pw->position(loc.x+=dx, loc.y+=dy); show(); }
	virtual void hide() { pw->hide(); }
	virtual void show() { pw->show(); }
	virtual void attach(Window&) = 0;

	Point loc;
	int width;
	int height;
	string label;
	Callback do_it;

	virtual ~Widget() { }

Gui.h, Gui.cpp 全ソースコード
Window.h, Window.cpp 全ソースコード
Simple_window.h, Point.h, main.cpp 全ソースコード

[C++] ”プログラミング入門” : GUIソースコード修正 Graph.h, Graph.cpp

[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]

最もボリュームがあるのがGraphファイルです。

FLTK1.1に対応した内容なのでFLTK1.3.8が使えるように書き換えました。コードがコメントアウトになっているところは復活させるかもしれないので残しておきました。

C++では自前で用意すべきerror関数がないのはご愛嬌でしょうか。

あれだけの多作家ですからコードのメンテナンスができていないところに人間味を感じます。ただ絶版にはなっていないので出版社含めちゃんとして欲しいですね。

2022/6/17追記:
ストラウストラップ氏HPのsupport code for PPP2 (tar ball)にfltk.hを含むtarがあります。fltk.hはFLTKの各種ヘッダファイルをグループ化したものです。FLTK1.1でもFLTK1.3.8でも同じように使えるはずです。

#ifndef GRAPH_GUARD
#define GRAPH_GUARD 1

#include "Point.h"
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath> // コメントアウトになっていた

using std::string; using std::initializer_list;
using std::vector; using std::cout;

// このエラー関数が存在していなかった
void error (const char* message) ;

namespace Graph_lib {
#undef major
#undef minor

struct Color {
	enum Color_type {
		red=FL_RED, blue=FL_BLUE, green=FL_GREEN,
		yellow=FL_YELLOW, white=FL_WHITE, black=FL_BLACK,
		magenta=FL_MAGENTA, cyan=FL_CYAN, dark_red=FL_DARK_RED,
		dark_green=FL_DARK_GREEN, dark_yellow=FL_DARK_YELLOW, dark_blue=FL_DARK_BLUE,
		dark_magenta=FL_DARK_MAGENTA, dark_cyan=FL_DARK_CYAN
	};
	enum Transparency { invisible = 0, visible=255 };

	Color(Color_type cc) :c(Fl_Color(cc)), v(visible) { }
	Color(Color_type cc, Transparency vv) :c(Fl_Color(cc)), v(vv) { }
	Color(int cc) :c(Fl_Color(cc)), v(visible) { }
	Color(Transparency vv) :c(Fl_Color()), v(vv) { }

	int as_int() const { return c; }
	char visibility() const { return v; }
	void set_visibility(Transparency vv) { v=vv; }
private:
	unsigned char v;
	Fl_Color c;
};

Graph.h, Graph.cpp 全ソースコード

[C++] 名著”プログラミング入門”のGUIを作成

[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]

ストラウストラップ氏の名著”プログラミング入門”(原書初版2008年)のGUIソースコード(日本語版P362)が現在の環境では動かないため関連ファイルを修正しました。

ヘッダファイル等はストラウストラップ氏のホームページから入手できます。こちらの方に手を入れました。

50個ほどのエラーを直していく気の遠くなるような作業でしたが、何とか復元できました。S氏はFLTKのインストールと設定は経験者でも難しいと説明しています。確かに普段使いしている私もライブラリの選択などで手間取りましたから、かなりの方が苦労していると思います。

ソースコードは次回以降アップします。