singlepost

Вопрос по PHP… =\ << На главную или назад  

Пишу онлайн-игру, нужно было сделать функцию апдейта ресурсов. В базе есть таблица, в которой прописано количество ресурсов, прибавляемых игроку за период времени.
Допустим, вот такая структура для одного типа ресурсов – power (это лишь кусок :) )
CREATE TABLE `resource_int` (
`id` mediumint(7) unsigned NOT NULL auto_increment PRIMARY KEY,
`power` smallint(4) unsigned default '1',
`power_t` smallint(5) unsigned default '1',
`power_div` mediumint(8) unsigned default '0',
`last_upd` timestamp NOT NULL default CURRENT_TIMESTAMP
)

`power_t` – период, за который игрок должен получить `power` ресурсов.

В функции я считаю время между последним обращением к таблице и текущим временем. Потом считаю, сколько за это время полльзователь должен получить ресурсов – выходит, как правило, дробное число. Остаток от дроби записываю в `power_div`, целое число ресурсов записываю в другую таблицу, в которой хранятся данные по ресурсам игрока. И перезаписываю время последней записи.
В коде это выглядит вот так:

function get_res_int($user)
{
$query = @mysql_query("SELECT * FROM `resource_int` WHERE `id` = '$user' LIMIT 1");
$result = @mysql_fetch_assoc($query);
return $result;
}

function update_resources($user)
{
$res_int = get_res_int($user);
$time = time() – strtotime($res_int['last_upd']);
$temp_power = $res_int['power'] * $time/$res_int['power_t'];

$new_power = floor($temp_power + $res_int['power_div']);

if($new_power == "0") $div_power = $temp_power;
else $div_power = $temp_power % $new_power;

@mysql_query("UPD?1?T?1? `players` SET `power` = `power` + '$new_power' WHERE `id` = '$user' LIMIT 1");
@mysql_query("UPD?1?T?1? `resource_int` SET `power_div` = '$div_power'', `last_upd` = NOW() WHERE `id` = '$user'");
}

И не покидает меня ощущение, что что то я сделал совсем не так, как надо!
Кто может оценить мой способ решения поставленной задачи?
Уверен, что есть более "красивый" вариант! При условии того, что вызываться эта функция будет ОЧЕНЬ часто, надо минимизировать затраты ресурсов…

10 ответов в теме “Вопрос по PHP… =\”

  1. 10
    Роман Чваников ответил:

    С одной стороны, я с Вами согласен. Если прошла ошибка – это не есть кошерно… Однако с другой стороны я лично никогда не любил выводить сообщения об ошибках в финальных релизах – только на стадии разработки, если "Something goes wrong"…
    Можно было бы реализовать функцию, заносящую информацию об ошибке в базу, но это чревато возможной новой ошибкой…
    Не знаю, почему, но я всегда предпочитал подавлять сообщения обошибках подобного рода – думаю, Вы согласитесь со мной, что пользователь обратит куда меньше внимания, если, к примеру, в результате ошибки ему не выведет количество пользователей онлайн, чем если появится какое то сообщение о том, что произошла какая то, непонятная ему, ошибка…

    Возможно, я ошибаюсь…

  2. 9
    Александр Афенов ответил:

    2Роман:
    меня, лично, например, сильно пугают "@".. проверки бы там.. возврат каких-нибудь стандартных значений, or die('bugaggaga") в конце концов, но только не подавление ошибок на sql-запросе

  3. 8
    Роман Чваников ответил:

    Блин, по ходу, вы все правы – я вчера сильно затупил и начал все решать через жопу… -__-
    2Даниил, а не могли бы Вы показать конкретно, что не нравится в самом коде кроме неграмотности алгоритма решения поставленной задачи?

  4. 7
    Даниил Малых ответил:

    Хоспати… Какой код… Ну нельзя так пугать! Теперь весь день кошмары будут видиться.:(

  5. 6
    Владимир Муромский ответил:

    Я собственно так и не понял, где ты используешь дробную часть, которую записал в таблицу power_div. Судя по данному куску кода, она просто пропадает, так в чем соль?:)
    Я бы предложил высылать клиенту столько золота, сколько там есть, а тот уже пусть сам округляет. Это гарантирует отсутствие ошибки на сервере

  6. 5
    Евгений Тихонов ответил:

    функция ceil() округляет в меньшую сторону =)

  7. 4
    Роман Чваников ответил:

    А черт его знает, почему я так не сделал… Слишком много времени провел за кодом, может… А может были причины… Я сейчас не могу сказать точно – сам сижу, думаю…

  8. 3
    Nikita Leksikov ответил:

    А зачем хранить дробную часть отдельно?
    Я бы сделал все в одном поле. При выводе/получении результата просто отбрасывать дробную часть.

  9. 2
    Роман Чваников ответил:

    Эмм… Если интересно разобрать логику, то почти.
    Функция update_resources вызывает функцию get_res_int, которая возвращает данные по динамике начисления ресурсов для игрока.
    После этого в функции update_resources происходит рассчет, сколько целых единиц должен получить игрок. Если 0 – записываем всю дробь в колонку "остаток" (power_div), если больше – записываем целую часть дроби в колонку с конкретным видом ресурсов в таблицу с данными игрока и дробь – в колонку "остаток" таблицы resource_int

    А дальше, например, выводим данные для конкретного игрока. Или, основываясь на обновленных данных, смотрим, может ли пользователь сделать то, или иное действие… Надеюсь не ошибиться, сказав, что это один из ключевых моментов в игре. Пока не доделаю до конца – точно ведь сказать не смогу :)

  10. 1
    Владимир Муромский ответил:

    Функция update_resources берет данные из таблицы resource_int, а после своих манипуляций записывает дробную часть ресурсов в таблицу power_div. Вопрос – что с ними происходит дальше? Нигде больше я обращения к этой таблице не вижу

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.