Elixir遊戲服設計六

2022-07-22 01:12:13 字數 3545 閱讀 8305

defmodule table do

@state_accept 0 #準備接入玩家

@state_ready 1 #開局準備?defdelegate [fetch(t, key), get_and_update(t, key, list)], to: map

defstruct [:config, :seats, :state]

defnew(config) do

%table,

state: @state_accept

}end

defis_full?(table) do

cur_count =enum.count(table.seats)

cur_count >=table.config.allow_count

enddefhas_player?(table, player_id) do

table.seats[player_id]

enddefcheck_in(table, player) do

update_in(table.seats, &(map.put(&1, player.base_info.id, player)))

enddefcheck_out(table, player_id) do

update_in(table.seats, &(map.delete(&1, player_id)))

endend

我們需要相關的配置table_config.txt

id,     allow_count,   base_gold,   need_gold,     desc

int, int, int, int, string

1, 4, 10, 480, 新手場

2, 4, 100, 4800, 中級場

3, 4, 1000, 48000, 高階場

這個txt可以由excel通過xslx2csv工具生成。然後我們利用table_config.txt 生成**配置table_config.ex.

我們當然可以在tableconfig裡經由excel檔案直接生成,那樣會更方便。

defmodule tableconfig do

module.register_attribute

__module__

, :column_names,

module.register_attribute

__module__

, :column_types,

module.register_attribute

__module__

, :config,

line_with_index = file.stream!(path.join([__dir__, "

table_config.txt

"]) , , :line)

|>stream.with_index

for <-line_with_index do

items = line |> string.split("

,") |> stream.map(&string.strip(&1))

case index do

0 ->@column_names items |> enum.map(&string.to_atom(&1))

1 ->@column_types items

|>stream.with_index

|> enum.map(fn -> end)

|>io.inspect

|> enum.into(%{})

_ ->new_items =items

|>stream.with_index

|> stream.map( &( typeconverter.convert(&1, @column_types) ) )

zip =enum.zip(@column_names, new_items)

@config enum.into(zip, %{})

io.inspect @config

# 以下函式花了我點時間,最後不得不通過模組屬性完成,我不知道有沒有其他方法

# 早期的版本是者這樣的

# config = enum.into(zip, %{})

# def get(unquote(config.id)) do

#   unquote(config) # 這裡會報錯,百思不得其解,在errormsg裡我是這樣用的,沒有問題。不知2者區別在哪

# end

defget(unquote(@config.id)) do

@config

endend

endend

最後上點測試**table_test.exs

defmodule tabeltest do

use exunit.case #

import pipehere

setup do

config = tableconfig.get(1)

table =table.new(config)

endtest

"table is full

", % do

new_table =

1..table.config.allow_count

|> stream.map(&player.new/1)

|> enum.reduce(table, fn p, acc ->table.check_in(acc, p) end)

assert new_table |>table.is_full?

endtest

"table has player

", % do

p1 = player.new(1)

p2 = player.new(2)

new_table =table.check_in(table, p1)

assert

table.has_player?(new_table, p1.base_info.id)

refute table.has_player?(table, p2.base_info.id)

endtest

"table check_in_and_out

", % do

p1 = player.new(1)

new_table =table.check_in(table, p1)

check_out_table =table.check_out(new_table, p1.base_info.id)

refute table.has_player?(check_out_table, p1.base_info.id)

endend

下一小節會從牌局開始吧,然後tableserver,然後讓它跑起來。

Elixir遊戲服設計五

現在想想也沒那麼難。保證原子性,無非就是需要某個單點去完成操作。那麼選擇玩家程序去做原子性工作就可以了。比如要重置某個任務,需要花費金幣和揹包裡某個物品,那麼大概的邏輯是這樣的。在玩家程序裡 def reset task task id do task.reset need with ok gold...

Elixir遊戲服設計一

在erlang遊戲服設計總結裡,我提到我想要的遊戲服設計方法,希望以應用做為基礎構建塊。最近我在學習elixir,它有很多 方便的語法糖以及很好用的庫,能夠解決我在遊戲中開發中碰到的很多繁瑣工作。因此我決定用它來做 練手,並期望下個專案中使用它。遊戲服的設計通常涉及如下東東 我將以乙個簡單的打牌遊戲...

簡單Elixir遊戲伺服器開篇

以前的elixir遊戲服設計系列種種原因沒有完成。後來雖然用elixir riak 完成了乙個麻將的初始版本,可惜公司也掛了。現在到新公司,比較空閒,想著像完成乙個心願一樣,還是重啟下吧 希望不要又爛尾 改頭換面叫簡單elixir遊戲伺服器系列。一些說明 0.沒怎麼寫過部落格,也懶得去研究了,說到哪...