|  |  |  | @ -1,11 +1,17 @@ | 
		
	
		
			
				|  |  |  |  | package main | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | import ( | 
		
	
		
			
				|  |  |  |  | 	"time" | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	"github.com/gen2brain/raylib-go/raylib" | 
		
	
		
			
				|  |  |  |  | ) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type ClientAuth struct { | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type Entity struct { | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type LoginState int | 
		
	
	
		
			
				
					|  |  |  | @ -24,12 +30,24 @@ const ( | 
		
	
		
			
				|  |  |  |  | 	BUTTON_STATE_PRESSED | 
		
	
		
			
				|  |  |  |  | ) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type Scale struct { | 
		
	
		
			
				|  |  |  |  | 	window rl.Vector2 | 
		
	
		
			
				|  |  |  |  | 	ui uint | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type ClientState struct { | 
		
	
		
			
				|  |  |  |  | 	auth *ClientAuth | 
		
	
		
			
				|  |  |  |  | 	login LoginState | 
		
	
		
			
				|  |  |  |  | 	login_button ButtonState | 
		
	
		
			
				|  |  |  |  | 	ui_scale uint | 
		
	
		
			
				|  |  |  |  | 	window_scale rl.Vector2 | 
		
	
		
			
				|  |  |  |  | 	scale Scale | 
		
	
		
			
				|  |  |  |  | 	screen rl.Rectangle | 
		
	
		
			
				|  |  |  |  | 	camera rl.Camera | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	command_queue chan interface{} | 
		
	
		
			
				|  |  |  |  | 	network_queue chan interface{} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	context *Entity | 
		
	
		
			
				|  |  |  |  | 	context_pos rl.Vector2 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | const ( | 
		
	
	
		
			
				
					|  |  |  | @ -37,19 +55,28 @@ const ( | 
		
	
		
			
				|  |  |  |  |   HEIGHT uint = 1000 | 
		
	
		
			
				|  |  |  |  | ) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func scale(original rl.Rectangle, ui_scale uint, window_scale rl.Vector2) rl.Rectangle { | 
		
	
		
			
				|  |  |  |  | func scale(original rl.Rectangle, scale Scale) rl.Rectangle { | 
		
	
		
			
				|  |  |  |  | 	return rl.Rectangle{ | 
		
	
		
			
				|  |  |  |  | X: original.X/window_scale.X, | 
		
	
		
			
				|  |  |  |  | 		Y: original.Y/window_scale.Y, | 
		
	
		
			
				|  |  |  |  | 		Width: original.Width*float32(ui_scale)/window_scale.X, | 
		
	
		
			
				|  |  |  |  | 		Height: original.Height*float32(ui_scale)/window_scale.Y, | 
		
	
		
			
				|  |  |  |  | 		X: original.X, | 
		
	
		
			
				|  |  |  |  | 		Y: original.Y, | 
		
	
		
			
				|  |  |  |  | 		Width: original.Width*float32(scale.ui)/scale.window.X, | 
		
	
		
			
				|  |  |  |  | 		Height: original.Height*float32(scale.ui)/scale.window.Y, | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func center(original rl.Rectangle, off_x, off_y int, window_scale rl.Vector2, width, height uint) rl.Rectangle { | 
		
	
		
			
				|  |  |  |  | func offset(original rl.Rectangle, off_x, off_y int, scale Scale) rl.Rectangle { | 
		
	
		
			
				|  |  |  |  | 	return rl.Rectangle{ | 
		
	
		
			
				|  |  |  |  | 		X: (float32(width) /window_scale.X - original.Width )/2 + float32(off_x)/window_scale.X, | 
		
	
		
			
				|  |  |  |  | 		Y: (float32(height)/window_scale.Y - original.Height)/2 + float32(off_y)/window_scale.Y, | 
		
	
		
			
				|  |  |  |  | 		X: original.X + float32(off_x)/scale.window.X, | 
		
	
		
			
				|  |  |  |  | 		Y: original.Y + float32(off_y)/scale.window.Y, | 
		
	
		
			
				|  |  |  |  | 		Width: original.Width, | 
		
	
		
			
				|  |  |  |  | 		Height: original.Height, | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func center(container, original rl.Rectangle) rl.Rectangle { | 
		
	
		
			
				|  |  |  |  | 	return rl.Rectangle{ | 
		
	
		
			
				|  |  |  |  | 		X: (container.Width  - original.Width )/2 + container.X, | 
		
	
		
			
				|  |  |  |  | 		Y: (container.Height - original.Height)/2 + container.Y, | 
		
	
		
			
				|  |  |  |  | 		Width: original.Width, | 
		
	
		
			
				|  |  |  |  | 		Height: original.Height, | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
	
		
			
				
					|  |  |  | @ -91,60 +118,104 @@ func button(rectangle rl.Rectangle, idle, hover, pressed rl.Color, text string, | 
		
	
		
			
				|  |  |  |  | 	return action, next_state | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func NetworkThread(network_queue chan interface{}) { | 
		
	
		
			
				|  |  |  |  | 	for(true) { | 
		
	
		
			
				|  |  |  |  | 		// TODO: remove
 | 
		
	
		
			
				|  |  |  |  | 		time.Sleep(time.Millisecond) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func LogicThread(state *ClientState) { | 
		
	
		
			
				|  |  |  |  | 	for(true) { | 
		
	
		
			
				|  |  |  |  | 		select { | 
		
	
		
			
				|  |  |  |  | 			case _ = <- state.command_queue: | 
		
	
		
			
				|  |  |  |  | 			case _ = <- state.network_queue: | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		time.Sleep(time.Millisecond) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func main() { | 
		
	
		
			
				|  |  |  |  | 	state := ClientState{ | 
		
	
		
			
				|  |  |  |  | 		auth: nil, | 
		
	
		
			
				|  |  |  |  | 		login: LOGIN_STATE_CREDENTIALS, | 
		
	
		
			
				|  |  |  |  | 		login_button: BUTTON_STATE_IDLE, | 
		
	
		
			
				|  |  |  |  | 		ui_scale: 1, | 
		
	
		
			
				|  |  |  |  | 		scale: Scale{ | 
		
	
		
			
				|  |  |  |  | 			ui: 1, | 
		
	
		
			
				|  |  |  |  | 		}, | 
		
	
		
			
				|  |  |  |  | 		camera: rl.NewCamera3D(rl.Vector3{}, rl.Vector3{}, rl.Vector3{}, 90, rl.CameraOrthographic), | 
		
	
		
			
				|  |  |  |  | 		context: nil, | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	go LogicThread(&state) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	rl.SetConfigFlags(rl.FlagWindowHighdpi) | 
		
	
		
			
				|  |  |  |  | 	rl.InitWindow(0, 0, "roleplay") | 
		
	
		
			
				|  |  |  |  | 	rl.SetExitKey(0) | 
		
	
		
			
				|  |  |  |  | 	rl.SetTargetFPS(60) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	state.window_scale = rl.GetWindowScaleDPI() | 
		
	
		
			
				|  |  |  |  | 	rl.SetWindowSize(int(float32(WIDTH)/state.window_scale.X), int(float32(HEIGHT)/state.window_scale.Y)) | 
		
	
		
			
				|  |  |  |  | 	state.scale.window = rl.GetWindowScaleDPI() | 
		
	
		
			
				|  |  |  |  | 	rl.SetWindowSize(int(float32(WIDTH)/state.scale.window.X), int(float32(HEIGHT)/state.scale.window.Y)) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	state.screen.Width  = float32(WIDTH) /state.scale.window.X | 
		
	
		
			
				|  |  |  |  | 	state.screen.Height = float32(HEIGHT)/state.scale.window.Y | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for(rl.WindowShouldClose() == false) { | 
		
	
		
			
				|  |  |  |  | 		if(state.auth == nil) { | 
		
	
		
			
				|  |  |  |  | 			// Draw login
 | 
		
	
		
			
				|  |  |  |  | 			rl.BeginDrawing() | 
		
	
		
			
				|  |  |  |  | 			rl.ClearBackground(rl.White) | 
		
	
		
			
				|  |  |  |  | 			rl.ClearBackground(rl.Black) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			logo_rect := scale(rl.Rectangle{Width: 1200, Height: 300}, state.ui_scale, state.window_scale) | 
		
	
		
			
				|  |  |  |  | 			logo_rect = center(logo_rect, 0, -300, state.window_scale, WIDTH, HEIGHT) | 
		
	
		
			
				|  |  |  |  | 			logo_rect := scale(rl.Rectangle{Width: 1200, Height: 300}, state.scale) | 
		
	
		
			
				|  |  |  |  | 			logo_rect = center(state.screen, logo_rect) | 
		
	
		
			
				|  |  |  |  | 			logo_rect = offset(logo_rect, 0, -250, state.scale) | 
		
	
		
			
				|  |  |  |  | 			rl.DrawRectangleRec(logo_rect, rl.Gray) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			form_rect := scale(rl.Rectangle{Width: 600, Height: 400}, state.ui_scale, state.window_scale) | 
		
	
		
			
				|  |  |  |  | 			form_rect = center(form_rect, 0, 150, state.window_scale, WIDTH, HEIGHT) | 
		
	
		
			
				|  |  |  |  | 			form_rect := scale(rl.Rectangle{Width: 600, Height: 400}, state.scale) | 
		
	
		
			
				|  |  |  |  | 			form_rect = center(state.screen, form_rect) | 
		
	
		
			
				|  |  |  |  | 			form_rect = offset(form_rect, 0, 200, state.scale) | 
		
	
		
			
				|  |  |  |  | 			rl.DrawRectangleRec(form_rect, rl.Gray) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			switch(state.login) { | 
		
	
		
			
				|  |  |  |  | 			case LOGIN_STATE_CREDENTIALS: | 
		
	
		
			
				|  |  |  |  | 				submit_rect := scale(rl.Rectangle{Width: 100, Height: 50}, state.ui_scale, state.window_scale) | 
		
	
		
			
				|  |  |  |  | 				submit_rect = center(submit_rect, 0, 300, state.window_scale, WIDTH, HEIGHT) | 
		
	
		
			
				|  |  |  |  | 				submit_rect := scale(rl.Rectangle{Width: 100, Height: 50}, state.scale) | 
		
	
		
			
				|  |  |  |  | 				submit_rect = center(form_rect, submit_rect) | 
		
	
		
			
				|  |  |  |  | 				submit_rect = offset(submit_rect, 0, 125, state.scale) | 
		
	
		
			
				|  |  |  |  | 				var submit_action bool | 
		
	
		
			
				|  |  |  |  | 				submit_action, state.login_button = button(submit_rect, rl.Black, rl.Brown, rl.Red, "Submit", 12, rl.White, state.login_button) | 
		
	
		
			
				|  |  |  |  | 				if submit_action { | 
		
	
		
			
				|  |  |  |  | 					state.login = LOGIN_STATE_ATTEMPTING | 
		
	
		
			
				|  |  |  |  | 					// TODO: real auth via network thread
 | 
		
	
		
			
				|  |  |  |  | 					state.auth = &ClientAuth{} | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			case LOGIN_STATE_ATTEMPTING: | 
		
	
		
			
				|  |  |  |  | 				text := "Logging in..." | 
		
	
		
			
				|  |  |  |  | 				text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, 20, 1.0) | 
		
	
		
			
				|  |  |  |  | 				text_rect := center(rl.Rectangle{Width: text_size.X, Height: text_size.Y}, 0, 0, state.window_scale, WIDTH, HEIGHT) | 
		
	
		
			
				|  |  |  |  | 				text_rect := center(form_rect, rl.Rectangle{Width: text_size.X, Height: text_size.Y}) | 
		
	
		
			
				|  |  |  |  | 				rl.DrawText(text, int32(text_rect.X), int32(text_rect.Y), 20, rl.Black) | 
		
	
		
			
				|  |  |  |  | 			case LOGIN_STATE_ERROR: | 
		
	
		
			
				|  |  |  |  | 				text := "Error: {TODO}" | 
		
	
		
			
				|  |  |  |  | 				text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, 20, 1.0) | 
		
	
		
			
				|  |  |  |  | 				text_rect := center(rl.Rectangle{Width: text_size.X, Height: text_size.Y}, 0, 0, state.window_scale, WIDTH, HEIGHT) | 
		
	
		
			
				|  |  |  |  | 				text_rect := center(form_rect, rl.Rectangle{Width: text_size.X, Height: text_size.Y}) | 
		
	
		
			
				|  |  |  |  | 				rl.DrawText(text, int32(text_rect.X), int32(text_rect.Y), 20, rl.Black) | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			rl.EndDrawing() | 
		
	
		
			
				|  |  |  |  | 		} else { | 
		
	
		
			
				|  |  |  |  | 			// Draw game
 | 
		
	
		
			
				|  |  |  |  | 			rl.BeginDrawing() | 
		
	
		
			
				|  |  |  |  | 			rl.ClearBackground(rl.Black) | 
		
	
		
			
				|  |  |  |  | 			rl.BeginMode3D(state.camera) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			if rl.IsMouseButtonPressed(rl.MouseButtonRight) { | 
		
	
		
			
				|  |  |  |  | 				state.context_pos = rl.GetMousePosition() | 
		
	
		
			
				|  |  |  |  | 				// TODO: Cast a ray into the bounding boxes
 | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			if state.context != nil { | 
		
	
		
			
				|  |  |  |  | 				 | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			rl.EndMode3D() | 
		
	
		
			
				|  |  |  |  | 			rl.EndDrawing() | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | 
 |